﻿WEBVTT

00:00:00.000 --> 00:00:06.000
Translated by visionNoob, KNU
https://github.com/insurgent92/CS231N_17_KOR_SUB

00:00:07.755 --> 00:00:11.682
CS231N 3강입니다.

00:00:11.682 --> 00:00:14.594
오늘은 손실함수(Loss functions)와
최적화(Optimization)을 배울겁니다.

00:00:14.594 --> 00:00:20.129
진도 나가기에 앞서 공지사항을 전달합니다.

00:00:21.094 --> 00:00:24.547
먼저, 첫 번째 과제가 생겼습니다.

00:00:24.547 --> 00:00:26.889
웹사이트에서 확인하실 수 있습니다.

00:00:26.889 --> 00:00:30.086
과제를 좀 늦게 내드렸기 때문에

00:00:30.086 --> 00:00:35.264
4월 20일 목요일 오후 11시 59분으로 기한을 변경합니다.

00:00:36.374 --> 00:00:42.702
앞으로 2주정도 라고 보시면 됩니다.

00:00:42.702 --> 00:00:49.087
그리고 변경된 기한으로 강의계획서를 업데이트하겠습니다.

00:00:49.087 --> 00:00:54.617
과제를 완료하면 zip파일로 Canvas에 업로드해야 하며

00:00:54.617 --> 00:00:57.779
가능한 빨리 채점을 하도록 하겠습니다.

00:00:58.799 --> 00:01:04.879
다음 사항은 여러분이 공지사항을 확인하려면
항상 Piazza를 체크해야 한다는 것입니다.

00:01:04.879 --> 00:01:11.432
이번주에 Piazza에 몇가지 예제 프로젝트를
공고해 놓을 것입니다.

00:01:11.432 --> 00:01:17.220
그래서 Stanford 커뮤니티와, 혹은 Stanford와 연계된
분들로부터 프로젝트 아이디와 관련된 예시를 부탁드렸는데,

00:01:17.220 --> 00:01:24.583
그리고 그 분들이 이 수업을 듣는 학생들과 함께 프로젝트를
진행하고 싶다는 제안을 해주셨습니다.

00:01:24.583 --> 00:01:26.986
그러니 Piazza에 공고를 확인해 보시고

00:01:26.986 --> 00:01:34.231
하고싶은 프로젝트가 있으면 자유롭게
프로젝트 멘토와 직접 얘기하면 되겠습니다.

00:01:34.231 --> 00:01:37.090
추가적으로 강의 홈피에 근무시간을
게시하였습니다.

00:01:37.090 --> 00:01:45.077
구글 캔린더로 게시하였고 학생들이 근무시간에 대해
많이 물어봐서 이번에 게시하였습니다.

00:01:45.077 --> 00:01:48.307
마지막 공지는 구글 클라우드 관련된 것입니다.

00:01:48.307 --> 00:01:54.331
구글 클라우드에서 우리 강의를 지원하므로

00:01:54.331 --> 00:02:00.687
여러분의 과제와 프로젝트를 수행하기 위해
구글 클라우드 크래딧 100$를 지급하였으며

00:02:00.687 --> 00:02:05.246
사용하는 방법은 추후 Piazza에 공지하겠습니다.

00:02:05.246 --> 00:02:11.977
공지사항에 대한 질문이 없으면 진도를 나가겠습니다.

00:02:13.440 --> 00:02:14.273
좋습니다.

00:02:15.559 --> 00:02:17.997
저번 2강을 복습해보면

00:02:17.997 --> 00:02:20.412
인식에서의 어려운 점을 살펴보았고

00:02:20.412 --> 00:02:24.476
데이터 중심의 방식에 초점을 마춰보았습니다.

00:02:24.476 --> 00:02:29.160
그리고 이미지 분류에 대해 배웠고
왜 이미지 분류가 어려운지, 그리고

00:02:29.160 --> 00:02:35.812
컴퓨터가 보는것과 사람이 보는 것의 차이가 있다는 것도 배웠습니다.

00:02:35.812 --> 00:02:42.124
그리고 분류를 어렵게하는 조명의 변화, 변형에 대해 다뤘고
왜 이게 그토록 어려운지에 대해 배웠습니다.

00:02:42.124 --> 00:02:47.912
인간의 시각체계는 이 일을 엄청 쉽게 하는데도 말이죠

00:02:47.912 --> 00:02:50.421
그리고 KNN 분류기도 배웠습니다.

00:02:50.421 --> 00:02:55.309
데이터 중심 접근방법 중에 가장 단순한 방법이었죠.

00:02:55.309 --> 00:03:00.824
그리고 CIFAR-10도 배웠습니다. 저기 좌상단에 보이는
이미지들이죠.

00:03:00.824 --> 00:03:05.787
CIFAR-10은 비행기, 자동차 등 10개의 카테고리가 있습니다.

00:03:05.787 --> 00:03:11.202
그리고 어떻게 KNN을 이용해서 학습 데이터를 가지고
각 카테고리 클래스를 분류하는

00:03:11.202 --> 00:03:15.746
결정 경계를 학습시킬 수 있는지도 배웠습니다.

00:03:15.746 --> 00:03:25.190
또한 크로스 벨리데이션데 대해서도 배웠고 트레인, 벨리데이션,
테스트셋으로 나눠서 하이퍼파라미터를 찾는 법도 배웠습니다.

00:03:25.190 --> 00:03:32.410
그리고 2강 마지막에는 Linear classification에 대해 배웠
습니다. Linear classifier는 뉴럴넷의 기본요소입니다.

00:03:32.410 --> 00:03:38.538
Linear classifier는 parametric classifier의
일종입니다. parametric classifier라는 것은

00:03:38.538 --> 00:03:45.444
트레이닝 데이터의 정보가 파라미터인  "행렬 W"로 요약된
다는 것을 뜻합니다. 그리고 W가 학습되는 것입니다.

00:03:45.444 --> 00:03:48.448
그리고 이 Linear classifier는 상당히 간단합니다.

00:03:48.448 --> 00:03:51.810
이미지를 입력받으면 하나의 긴 벡터로 폅니다.

00:03:51.810 --> 00:03:54.974
여기 이미지 x가 있고,

00:03:54.974 --> 00:04:02.918
이 이미지는 32x32x3 픽셀이고,
이를 긴 열벡터로 펼치게 됩니다.

00:04:04.344 --> 00:04:09.722
32x32는 이미지의 높이와 너비이며 3은
이미지의 채널 red, green, blue 입니다.

00:04:09.722 --> 00:04:13.561
그리고 파라미터 "행렬 W"가 있는데

00:04:13.561 --> 00:04:18.517
이 행렬은 아까 만들었던 이미지 픽셀과 연산하여

00:04:18.517 --> 00:04:24.387
CIFAR-10의 각 10개의 클래스에 해당하는
클래스 스코어를 만들어줍니다.

00:04:24.387 --> 00:04:29.617
그리고 해석해보면 스코어가 더 큰 값은

00:04:29.617 --> 00:04:34.881
가령 고양이 클래스의 스코어가 더 크다는 것은
분류기가 이 이미지가 고양이일것 같다고 생각하는 것입니다.

00:04:34.881 --> 00:04:42.443
반대로 개나 자동차 클래스의 스코어가 더 낮다는 것은
이 이미지가 개나 자동차일 확률이 낮다는 것을 의미하는 것입니다.

00:04:42.443 --> 00:04:51.625
또한 지난 수업에서 설명이 좀 부족했던 부분이 있었습니다.
Linear clssification을 각 클래스 템플릿으로 보는 것인데

00:04:51.625 --> 00:05:02.444
좌하단의 다이어그램을 보시면, 행렬 W에는 각 10개의 클래스와
이미지의 모든 픽셀에 대응되는 하나씩의 요소가 있습니다.

00:05:02.444 --> 00:05:06.554
그리고 이 것은 "이 픽셀이 클래스를 결정하는데
얼마나 중요한 역할을 하는지"를 의미합니다.

00:05:06.554 --> 00:05:12.412
행렬 W의 각 행들이 해당하는 그 클래스의
템플릿이 되는 것입니다.

00:05:12.412 --> 00:05:22.551
행렬 W의 각 행은 "이미지의 픽셀 값"과 "해당 클래스" 사이의
가중치가 되기 때문에

00:05:22.551 --> 00:05:29.900
그렇기 때문에 우리가 각 행을 풀어서 다시 한 이미지로 재구성하면
각 클래스에 대응하는 학습된 템플릿을 볼 수 있었습니다.

00:05:29.900 --> 00:05:35.399
그리고 또한 Linear clssification이 고차원 공간에서의
일종의 "결정 경계"를 학습한다는 측면으로 볼 수 있는데,

00:05:35.399 --> 00:05:43.774
그 공간의 차원은 이미지의 픽셀 값에 해당하는 것입니다.

00:05:43.774 --> 00:05:47.571
지난 시간에 여기까지 진행했습니다.

00:05:47.571 --> 00:05:54.141
지난 시간에는 Linear classifier에 대한 간략한 아이디어만
배우고 끝났습니다.

00:05:54.141 --> 00:05:57.554
그때는 실제로 행렬W를 어떻게 만드는지는
다루지 않았습니다.

00:05:57.554 --> 00:06:02.628
가장 좋은 행렬W를 구하는데 어떻게 트레이닝 데이터를
활용해야 하는지는 언급하지 않았었습니다.

00:06:02.628 --> 00:06:08.292
지난 시간에는 임의의 행렬 W를 사용했었고,

00:06:08.292 --> 00:06:12.068
그 행렬 W를 가지고 각 이미지에 해당하는
10개의 클래스 스코어를 계산하였습니다.

00:06:12.068 --> 00:06:15.597
이 때의 클래스 스코어는 좋을수도, 나쁠수도 있었습니다.
(임의로 정한 것이니까)

00:06:15.597 --> 00:06:20.833
여기 간단한 예시가 있는데 세개의 트레이닝 데이터에 대한

00:06:20.833 --> 00:06:26.046
임의의 행렬W를 가지고 예측한 10개의 클래스 스코어입니다.

00:06:26.046 --> 00:06:29.506
굵게 표시한 각 스코어를 보면 더 좋은것도 있고
나쁜 것도 있다는 것을 볼 수 있습니다.

00:06:29.506 --> 00:06:35.924
예컨데 왼쪽의 이미지를 보면 고양이이죠
우리는 인간이니까 아주 쉽게 알 수 있죠.

00:06:35.924 --> 00:06:41.068
하지만 고양이에 부여된 확률을 보면,
(확률이 아니라 스코어죠)

00:06:41.068 --> 00:06:48.082
이 분류기가 cat에는 2.9점을 줬습니다.

00:06:48.082 --> 00:06:51.018
반면 frog에는 3.78점을 줬군요

00:06:51.018 --> 00:06:57.920
이 분류기는 별로 좋아보이지 않습니다. 우리는 정답 클래스(고양이)
가 가장 높은 점수가 되는 분류기를 원합니다.

00:06:57.920 --> 00:07:02.729
반면 다른 예를 살펴봅시다. 자동차를 보면

00:07:02.729 --> 00:07:06.819
자동차 이미지에서는 자동차의 스코어가 제일 높습니다.
좋은 거죠

00:07:06.819 --> 00:07:14.357
개구리의 예를 보면 스코어가 -4입니다. 오히려
다른 스코어보다도 훨씬 낮습니다. 엄청 안좋은 것입니다.

00:07:14.357 --> 00:07:16.531
이렇게 분석하는 방법은 좋지 않습니다.

00:07:16.531 --> 00:07:20.654
스코어를 눈으로 훑으면서 어느게 좋고
어느게 나쁜지 살펴보기만 하는것은 좋은 생각이 아닙니다.

00:07:20.654 --> 00:07:25.264
이런 알고리즘을 만들고, 어떤 W가 가장 좋은지를
결정하기 위해서는

00:07:25.264 --> 00:07:31.032
지금 만든 W가 좋은지 나쁜지를 정량화 할 방법이 필요합니다.

00:07:31.032 --> 00:07:41.987
W를 입력으로 받아서 각 스코어를 확인하고 이 W가 지금 얼마나
거지같은지를 정량적으로 말해주는 것이 바로 손실함수입니다.

00:07:41.987 --> 00:07:49.782
이번 강의에서는 Image classification에서 쓸만한
몇가지 손실함수를 소개해 드리도록 하겠습니다.

00:07:49.782 --> 00:07:52.683
손실함수가 어떤 일을 해야하는지 한번 생각해 보세요.

00:07:52.683 --> 00:07:58.498
임의의 값 W가 얼마나 좋은지 나쁜지를 정량화해 줘야 합니다.

00:07:58.498 --> 00:08:04.770
우리가 실제로 원하는 것은, 행렬 W가 될 수 있는
모든 경우의 수에 대해서

00:08:04.770 --> 00:08:10.688
"가장 덜 구린"  W가 무엇인지를 찾고싶은 것입니다.

00:08:10.688 --> 00:08:12.860
이 과정이 바로 "최적화 과정" 이며

00:08:12.860 --> 00:08:16.276
최적화에 대해서는 좀 있다가 다시 다루겠습니다.

00:08:16.276 --> 00:08:21.003
일단 문제를 좀 줄여보겠습니다. 클래스 10개는
다루기가 불편하니깐요

00:08:21.003 --> 00:08:28.886
이번 강의에서는 클래스를 3개로 하는
toy 데이터셋을 사용하겠습니다.

00:08:28.886 --> 00:08:44.425
이 예제에서 "고양이" 클래스는 잘 분류되지 못했고 "자동차" 는 잘됐고
"개구리"는 최악입니다. 개구리 점수는 다른 것보다 더 낮습니다.

00:08:44.425 --> 00:08:48.817
이를 좀 더 공식화해 봅시다.
손실 함수에 대해 생각해보면

00:08:48.817 --> 00:08:52.870
트레이닝 데이터 X와 Y가 있고

00:08:52.870 --> 00:08:56.196
보통 X는 알고리즘의 입력에 해당하고

00:08:56.196 --> 00:09:05.407
Image classification 알고리즘이라면 X는 이미지가 될 것이고
 Y는 예측하고자 하는 것이 될 것입니다.

00:09:05.407 --> 00:09:08.930
보통은 Y는 레이블이나 타겟이라고 합니다.

00:09:08.930 --> 00:09:16.797
Image classification의 경우라면 각 이미지를 CIFAR-10
의 10개의 카테고리 중 하나로 분류하는 것이고,

00:09:16.797 --> 00:09:24.414
여기에서 레이블 y는 1에서 10 사이의 정수 값이 됩니다.
프로그래밍 언어에 따라 0에서 9 일수도 있습니다.

00:09:24.414 --> 00:09:30.270
어쨌든 이 y라는 정수값은 각 이미지 x의
정답 카테고리를 의미합니다.

00:09:30.270 --> 00:09:42.838
앞서 예측 함수를 정의했었죠 입력 이미지 x와 행렬 W를 입력으로 받아서
y를 예측하는 것입니다.

00:09:42.838 --> 00:09:46.446
Image classification 문제라면 y는 10개가 되겠습니다.
(CIFAR-10의 경우)

00:09:46.446 --> 00:09:49.938
그 다음 손실함수 L_i를 정의합니다.

00:09:49.938 --> 00:09:56.804
앞서 말씀드린 예측함수 f와 정답 값 Y를 입력으로 받아서는

00:09:56.804 --> 00:10:02.510
이 트레이닝 샘플을 얼마나 구리게 예측하는지를
정량화 시켜 줍니다.

00:10:02.510 --> 00:10:10.478
그리고 최종 Loss인 "L"은 우리 데이터 셋에서
각 N개의 샘플들의 Loss의 평균이 됩니다.

00:10:10.478 --> 00:10:13.432
이 함수는 아주 일반적인 공식입니다.

00:10:13.432 --> 00:10:16.421
그리고 Image classification 외에도 다양하게
확장할 수 있습니다.

00:10:16.421 --> 00:10:24.426
좀 더 나아가서 다른 딥러닝 알고리즘을 살펴보자면
어떤 알고리즘이던 가장 일반적으로 진행되는 일은,

00:10:24.426 --> 00:10:33.535
일단 어떤 X와 Y가 존재하고, 여러분이 만들 파라미터 W에
W가 얼마나 좋은지를 정량화하는 손실 함수를 만드는 것입니다.

00:10:33.535 --> 00:10:39.982
결국은 W의 공간을 탐색하면서 의트레이닝 데이터의
 Loss를 최소화하는 어떤 W를 찾게 될 것입니다.

00:10:41.081 --> 00:10:49.322
구체적으로 한 손실함수의 예를 들어보겠습니다.
이 손실함수는 Image classification에 아주 적합하기도 합니다.

00:10:49.322 --> 00:10:52.755
multi-class SVM loss를 대해 알아보겠습니다.

00:10:52.755 --> 00:10:59.602
아마 CS229에서 이진 SVM(Support Vector Machine)
본 적이 있을 것입니다.

00:11:00.662 --> 00:11:05.263
multi-class SVM은 여러 클래스를 다루기 위한
이진 SVM의 일반화된 형태입니다.

00:11:05.263 --> 00:11:11.797
CS229에서 다뤘던 이진 SVM은 두개의 클래스만 다룹니다.

00:11:11.797 --> 00:11:15.159
각 데이터는 Positive 또는 Negative로 분류될 뿐입니다.

00:11:15.159 --> 00:11:20.762
하지만 여긴 10개의 카테고리가 있기 때문에
여러개의 클래스를 다루려면 이 개념을 좀더 일반화 시켜야 합니다.

00:11:20.762 --> 00:11:24.854
그렇기 때문에 multi-class SVM의 손실함수는
조금 재밌게 생겼습니다.

00:11:24.854 --> 00:11:29.801
지금부터는 이에 대해 좀 더 자세히 알아보도록 하겠습니다.

00:11:29.801 --> 00:11:35.584
각각의 트레이닝 데이터에서 Loss L_i
를 구하는 방법 부터 살펴보겠습니다.

00:11:35.584 --> 00:11:43.373
L_i를 구하기 위해 우선  "True인 카테고리" 를 제외한
"나머지 카테고리 Y"의 합을 구합니다.

00:11:43.373 --> 00:11:46.204
다시말해 맞지 않는 카테고리를 전부 합치는 것입니다.

00:11:46.204 --> 00:11:52.509
그리고 올바른 카테고리의 스코어와 올바르지 않은 카테고리의
스코어를 비교해 봅니다.

00:11:52.509 --> 00:11:59.589
만약 올바른 카테고리의 점수가 올바르지 않은 카테고리의
점수보다 더 높으면

00:11:59.589 --> 00:12:03.814
그리고 그 격차가 일정 마진(safety margin) 이상이라면,
이 예시에서는 그 마진을 1로 두었죠

00:12:03.814 --> 00:12:14.661
이 경우는 True인 스코어가 다른 false 카테고리보다 훨씬 더
크다는 것을 의미합니다.

00:12:14.661 --> 00:12:17.663
그렇게 되면 Loss는 0이 됩니다.

00:12:17.663 --> 00:12:21.703
이미지 내 정답이 아닌 카테고리의 모든 값들을 합치면

00:12:21.703 --> 00:12:27.155
그 값이 바로 한 이미지의 최종 Loss 가 되는 것입니다.

00:12:27.155 --> 00:12:31.994
그리고 전체 트레이닝 데이터 셋에서 그 Loss들의 평균을 구합니다.

00:12:31.994 --> 00:12:41.263
이걸 수식화 시키면 if-then 으로 표현 할 수 있습니다.
(if:)정답 클래스의 스코어의 점수가 제일 높으면

00:12:41.263 --> 00:12:49.327
그럼 "then" 은 다음과 같이 나타낼 수 있습니다.
then, max(0,s_j - s_yj + 1).

00:12:50.496 --> 00:12:54.294
그리고 수식을 보다가 헷갈리 때가 있는데

00:12:54.294 --> 00:13:00.920
그러면 직접 손으로 써보면서 이해하면 도움이 됩니다.

00:13:00.920 --> 00:13:06.805
그리고 0과 다른 값의 최댓값, Max(0, value)
과 같은 식으로 손실 함수를 만드는데,

00:13:06.805 --> 00:13:14.627
이런 류의 손실 함수를 "hinge loss"(경첩)라고 부르기도 합니다.
그래프의 모양때문에 붙혀진 이름입니다.

00:13:14.627 --> 00:13:22.275
여기에서 x축은 S_Yi입니다.
실제 정답 클래스의 스코어입니다.

00:13:22.275 --> 00:13:25.353
그리고 y축은 Loss입니다.

00:13:25.353 --> 00:13:34.174
정답 카테고리의 점수가 올라갈수록 Loss가 선형적으로
줄어드는 것을 알 수 있습니다.

00:13:34.174 --> 00:13:40.235
이 로스는 0이 된 이후에도 Safety margin 을
넘어설 때 까지 더 줄어듭니다.

00:13:40.235 --> 00:13:44.402
Loss가 0이 됐다는 건 클래스를 잘 분류했다는 뜻입니다.

00:13:45.550 --> 00:13:47.836
질문 있나요?

00:13:47.836 --> 00:13:52.410
[죄송합니다만, S_Yi가 뭔가요?]

00:13:52.410 --> 00:13:55.170
[정답 스코어인가요? ]

00:13:55.170 --> 00:13:56.321
네 질문은

00:13:56.321 --> 00:14:00.097
S가 어떤 것이고 S_Yi가 어떤 것인지 입니다.

00:14:00.097 --> 00:14:07.246
S는 분류기의 출력으로 나온 예측된 스코어 입니다.

00:14:07.246 --> 00:14:13.942
가령 1이 고양이고 2가 개면
S_1은 고양이 스코어 S_2는 개 스코어 인 것이죠

00:14:13.942 --> 00:14:21.056
Y_i는 이미지의 실제 정답 카테고리 입니다. 정수 값이죠

00:14:21.056 --> 00:14:32.683
그러니 S_Y_i는 트레이닝 셋의 i번째 이미지의
정답 클래스의 스코어인 것입니다.

00:14:32.683 --> 00:14:33.870
질문 있으십니까?

00:14:33.870 --> 00:14:35.921
[질문 중]

00:14:35.921 --> 00:14:38.677
질문은, 그럼 정확히 무엇을 계산하는 것인지 입니다.

00:14:38.677 --> 00:14:44.590
무엇을 계산하는지는 흥미로운 주제입니다.
앞으로 예제를 살펴보면 답을 찾을 수 있을 것입니다.

00:14:44.590 --> 00:14:51.984
이 Loss가 말하고자 하는 것은 정답 스코어가
다른 스코어들보다 높으면 좋다는 것입니다.

00:14:51.984 --> 00:14:58.364
정답 스코어는 safty margin(여기에서 1) 을 두고
다른 스코어들 보다 훨씬 더 높아야 합니다.

00:14:58.364 --> 00:15:06.534
충분히 높지 않으면 Loss가 높아지게 됩니다.

00:15:06.534 --> 00:15:13.223
3개의 트레이닝 데이터셋을 가지고 예를 들어보면
좀 더 감을 익힐 수 있을 것입니다.

00:15:13.223 --> 00:15:19.513
여기서는 case space notation을 제거하고
zero one notation을 사용했습니다.

00:15:19.513 --> 00:15:26.186
맨 왼쪽의 예시를 보면서 multi-class SVM loss가
계산 되는 과정을 살펴보자면

00:15:26.186 --> 00:15:31.913
우선 정답이 아닌 클래스를 순회합니다.

00:15:31.913 --> 00:15:39.089
Cat은 정답 클래스이니, Car와  Flog 클래스를 순회합니다.
이제 다시 Car의 경우를 살펴보면

00:15:41.088 --> 00:15:48.782
이제 (Car 스코어) 5.1 - (Cat 스코어) 3.2 + 1(magin)
을 구합니다. Cat과 Car를 비교할때 짐작할 수 있는 것은

00:15:49.969 --> 00:15:55.134
Car가 Cat보다 더 높으니까 Loss가 발생할 것이라는 것입니다.

00:15:55.134 --> 00:15:59.153
이 고양이 이미지의 예시를 보면

00:15:59.153 --> 00:16:03.387
2.9의 손실이 발생합니다.
Cat-Car 와 Car-Flog를 비교해보면

00:16:03.387 --> 00:16:08.480
Car는 3.2, Flog는 -1.7의 에러가 발생합니다.

00:16:08.480 --> 00:16:16.409
Cat 스코어는 Frog 스코어보다 훨씬 그므로
Loss는 0이라고 할 수 있습니다.

00:16:16.409 --> 00:16:23.094
고양이 이미지의 Multiclass-SVM Loss는
이런 클래스쌍의 Loss의 합이 되며

00:16:23.094 --> 00:16:27.112
즉 2.9 + 0 = 2.9 가 되는 것입니다.

00:16:27.112 --> 00:16:34.567
여기에서 2.9라는 숫자가 "얼마나 분류기가 이 이미지를
구리게 분류하는지" 에 대한 척도가 되겠습니다.

00:16:35.795 --> 00:16:41.574
이런 작업은 여러번 반복합니다.
 Car 클래스에 다시한번 해보면

00:16:41.574 --> 00:16:52.072
Car와 Cat을 비교해 볼 것입니다. Car 스코어가 Cat 스코어보다 높기
때문에 여기에서 Loss는 0이 될 것입니다.

00:16:52.072 --> 00:16:57.557
Car 와 Frog도 비교해보면 Car의 스코어가 Frog보다 훨씬
더 크다는 것을 알 수 있습니다.

00:16:57.557 --> 00:17:02.993
그러므로 Car 의 경우는 전체 Loss도 0이 되겠습니다.

00:17:02.993 --> 00:17:09.051
이미 다들 감을 잡으셨겠지만 개구리, frog의 경우도 한번 봅시다.

00:17:09.051 --> 00:17:14.895
Frog와 Cat을 보면 엄청 큰 Loss가 발생함을 알 수 있습니다.
Flog스코어가 엄청 낮기 때문이죠. Car와의 경우도 같습니다.

00:17:14.895 --> 00:17:19.697
또한 Frog 스코어 자체가 엄청 낮기 때문이죠.
결국 전체 Loss는 12.9가 됩니다.

00:17:21.150 --> 00:17:26.578
그리고 전체 트레이닝 셋의 최종 Loss는
각 트레이닝 이미지의 Loss들의 평균이 되겠습니다.

00:17:26.578 --> 00:17:29.277
대략 5.3정도 나오는 걸 볼 수 있습니다.

00:17:29.277 --> 00:17:34.929
이것이 의미하는 바는, 우리의 분류기가 5.3점 만큼 이 트레이닝 셋을
구리게 분류하고 있다는 "정량적 지표" 가 되는 것입니다.

00:17:34.929 --> 00:17:36.732
질문 있으십니까?

00:17:36.732 --> 00:17:39.152
[질문 중]

00:17:39.152 --> 00:17:41.920
질문은 바로, "1을 더하는 것"은 어떻게 결정하는 것인지 입니다.
(safety margin 이 1이었음)

00:17:41.920 --> 00:17:43.574
아무 좋은 질문입니다.

00:17:43.574 --> 00:17:46.662
이게 아무 숫자나 막 끼워 넣은 것 같아 보이고

00:17:46.662 --> 00:17:52.532
이게 또 손실 함수에서 상수 텀으로 자리잡고 있고
그래서 보기에 불쾌할 수도 있는데요

00:17:52.532 --> 00:18:00.305
이게 임의로 선택한 숫자같아 보이긴 하지만, 우리는 사실 손실함수의
"스코어가 정확이 몇인지"는 신경쓰지 않습니다.

00:18:00.305 --> 00:18:05.389
우리가 궁금한건 여러 스코어 간의 상대적인 차이인 것입니다.

00:18:05.389 --> 00:18:08.944
우리가 관심있어 하는건 오로지 정답 스코어가 다른 스코어에 비해
얼마나 더 큰 스코어를 가지고 있는지 입니다.

00:18:08.944 --> 00:18:14.742
행렬 W를 전체적으로 스케일링한다고 생각해 보면
결과 스코어도 이에 따라 스케일이 바뀔 것입니다.

00:18:14.742 --> 00:18:20.808
이와 관련된 내용이 온라인 코스 노트에 자세히 나와 있습니다.

00:18:20.808 --> 00:18:24.362
그걸 보면 1 이라는게 별 상관 없다는 것을 알게 될 것입니다.

00:18:24.362 --> 00:18:32.625
1이라는 파라미터는 없어지고, W의 스케일에 의해 상쇄됩니다.

00:18:32.625 --> 00:18:35.489
자세한 내용은 온라인 코스노트를 확인해 주시면 되겠습니다.

00:18:37.953 --> 00:18:45.374
그 Loss가 실제무 무슨 일을 하는지를 직관적으로 이해하는
것이 중요하므로 다른 질문들로 다시 접근해 보겠습니다.

00:18:45.374 --> 00:18:53.349
만약 Car 스코어가 조금 변하면 Loss에는 무슨 일이 일어날까요?

00:18:53.349 --> 00:18:54.182
아이디어 있으십니까?

00:18:56.479 --> 00:18:59.856
다들 대답하기 무서워 하는것 같네요

00:18:59.856 --> 00:19:00.689
정답?

00:19:00.689 --> 00:19:04.272
[대답 하는 학생]

00:19:06.983 --> 00:19:13.333
대답은 우리가 Car의 스코어를 조금 바꾸더라고
Loss가 바뀌지 않을 것이라고 대답했습니다.

00:19:13.333 --> 00:19:21.918
다시 SVM loss를 상기해보면 이 loss는 오직 정답 스코어와
그 외의 스코어와의 차이만 고려했습니다. 따라서 이 경우에는

00:19:21.918 --> 00:19:25.506
Car 스코어가 이미 다른 스코어들보다 엄청 높기 때문에

00:19:25.506 --> 00:19:35.437
여기 스코어를 조금 바꾼다고 해도, 서로 간의 간격(Margin)은 여전히
유지될 것이고, 결국 Loss는 변하지 않습니다. 계속 0일 것입니다.

00:19:36.870 --> 00:19:40.150
다음 질문은 SVM Loss가 가질 수 있는
최댓/최솟값이 어떻게 될까요?

00:19:43.265 --> 00:19:44.445
[대답하는 학생]

00:19:44.445 --> 00:19:45.764
잘 못들었습니다?

00:19:45.764 --> 00:19:52.018
최솟값은 0이 되겠죠. 왜냐하면 모든 클래스에 걸쳐서

00:19:52.018 --> 00:19:57.357
정답 클래스의 스코어가 제일 크면
모든 트레이닝 데이터에서 loss가 0이 될테니깐요

00:19:57.357 --> 00:20:03.495
그리고 다시 이 손실 함수가 hinge loss 모양이라는 점을 고려해 보면,

00:20:03.495 --> 00:20:07.981
만약 정답 클래스 스코어가 엄청 낮은 음수 값을 가지고
있다고 생각해보면, 아마 Loss가 무한대 일 것입니다.

00:20:07.981 --> 00:20:11.538
그러니 최솟값은 0이고 최댓값을 무한대 일 것입니다.

00:20:11.538 --> 00:20:16.120
또 한가지는, 파라미터를 초기화하고
처음부터 학습시킬때

00:20:16.120 --> 00:20:21.242
보통은 행렬W를 임의의 작은 수로 초기화시키는데, 그렇게되면

00:20:21.242 --> 00:20:25.535
처음 학습 시에는 결과 스코어가 임의의 일정한 값을 갖게 됩니다.

00:20:25.535 --> 00:20:31.449
그렇다면 만약 모든 스코어 S가 거의 "0에 가깝고" 그리고
"값이 서로 거의 비슷하다면"

00:20:31.449 --> 00:20:35.740
Multiclass SVM에서 Loss가 어떻게 될 것 같습니까?

00:20:35.741 --> 00:20:37.502
- [학생이 답변]

00:20:37.502 --> 00:20:43.248
네, 답변은 "클래스의 수 - 1" 이었습니다.

00:20:42.448 --> 00:20:53.738
왜냐면 Loss를 계산할때 정답이 아닌 클래스를 순회합니다. 그러면
C - 1 클래스를 순회하겠죠. 비교하는 두 스코어가 거의 비슷하니

00:20:53.738 --> 00:20:57.536
Margin때문에 우리는 1 스코어를 얻게 될 것입니다.
그리고 전에 Loss는 C - 1을 얻게 되는 것이죠

00:20:57.536 --> 00:21:01.964
이는 실제로 유용합니다. 특히 "디버깅 전략"으로 말이죠

00:21:01.964 --> 00:21:04.734
여러분들이 이런 전략을 가지고 트레이닝을 시작한다면

00:21:04.734 --> 00:21:08.082
여러분들은 Loss가 어떻게 될지를 짐작할 수 있게 됩니다.

00:21:08.082 --> 00:21:14.999
다시말해 트레이닝을 처음 시작할때 Loss가 C-1이 아니라면

00:21:14.999 --> 00:21:16.353
아마 버그가 있는 것이고 고쳐야 할 것입니다.

00:21:16.353 --> 00:21:20.905
실제로 아무 유용합니다.

00:21:21.886 --> 00:21:31.487
또 다른 질문입니다. SVM Loss는 정답인 클래스는 빼고 다 더했습니다.
그렇다면 정답인 놈도 같이 더하면 어떻게될까요?

00:21:31.487 --> 00:21:34.323
만약 다 더하면?

00:21:34.323 --> 00:21:36.034
- [학생이 대답]

00:21:36.034 --> 00:21:39.326
답은 Loss에 1이 더 증가한다는 것입니다.

00:21:39.326 --> 00:21:45.052
일제로 우리가 정답 클래스만 빼고 계산하는 이유는,
일반적으로 Loss가 0이 되야지만

00:21:45.052 --> 00:21:52.755
우리가 "아무것도 잃는 것이 없다"고 쉽게 해석할 수 있으며.

00:21:52.755 --> 00:21:56.484
Loss에 모든 클래스를 다 더한다고 해서
다른 분류기가 학습되는 것은 아닙니다.

00:21:56.484 --> 00:22:02.729
하지만 관례상 정답 클래스는 빼고 계산을 하며,
그렇게 되면 최소 Loss는 0이 됩니다.

00:22:04.931 --> 00:22:08.008
또다른 질문입니다. Loss에서 전체 합을 쓰는게 아니라
평균을 쓰면 어떻게 될까요?

00:22:09.943 --> 00:22:11.233
- [학생]

00:22:11.233 --> 00:22:13.076
네 답은 영향을 미치지 않는다는 것입니다.

00:22:13.076 --> 00:22:15.788
클래스의 수는 어짜피 정해져 있으니

00:22:15.788 --> 00:22:20.500
평균을 취한다는건 그저 손실 함수를 리스케일 할 뿐입니다.

00:22:20.500 --> 00:22:23.991
그러니 상관이 없을 것입니다.
단지 스케일만 변할 뿐입니다.

00:22:23.991 --> 00:22:29.664
왜냐하면 우리는 스코어 값이 몇인지는 신경쓰지 않기 때문입니다.

00:22:30.541 --> 00:22:37.934
자 이제 또 다른 질문입니다. 만약 우리가 손실함수를
아래와 같이 제곱 항으로 바꾸면 어떻게 될까요?

00:22:37.934 --> 00:22:42.968
그럼 결과가 달라질까요 같이질까요?

00:22:42.968 --> 00:22:44.178
- [학생]

00:22:44.178 --> 00:22:45.213
결과는 달라질 것입니다.

00:22:45.213 --> 00:22:50.903
좋은것 과 나쁜것 사이의 트레이드 오프를
비 선형적인 방식으로 바꿔주는 것인데요

00:22:50.903 --> 00:22:54.264
그렇게 되면 손실함수의 계산 자체가 바뀌게 됩니다.

00:22:54.264 --> 00:22:59.915
실제로도 squared hinge loss를 종종 사용합니다.

00:22:59.915 --> 00:23:05.066
이는 여러분들이 손실함수를 설계할때
쓸 수 있는 한가지 방법이 될 수 있습니다.

00:23:05.066 --> 00:23:07.831
질문 있나요?

00:23:07.831 --> 00:23:11.596
- [학생]

00:23:11.596 --> 00:23:16.760
질문은, 왜 굳이 제곱 항을 고려해야 하냐는 것입니다.

00:23:16.760 --> 00:23:22.281
손실 함수의 요지는 "얼마나 구린지"를 정량화 하는 것입니다.

00:23:22.281 --> 00:23:25.143
그리고 분류자가 다양한 종류의 실수를 저지르고 있다면,

00:23:25.143 --> 00:23:30.141
어떻게 해야 이 분류기가 만드는 다양한 Loss들 마다
상대적으로 패널티를 부여할 수 있을까요?

00:23:30.141 --> 00:23:37.834
만약 Loss에 제곱을 한다면 이제 "엄청 엄청
안좋은 것들" 은 정말로 "곱절로 안좋은 것" 이 됩니다.

00:23:37.834 --> 00:23:39.192
그러니 정말로 나빠지게 되는겁니다.

00:23:39.192 --> 00:23:43.623
마치 우리가 심하게 잘못 분류되는 것들을
정말 원하지 않는 것이 됩니다.

00:23:43.623 --> 00:23:47.321
반면에 hinge loss를 사용하게 되면

00:23:47.321 --> 00:23:52.553
실제로 "조금 잘못된 것" 과 "많이 잘못된 것" 을 크게 신경쓰지
않게 되는 것입니다.

00:23:52.553 --> 00:23:57.051
만약 "많이 잘못된 것" 이 있다면 우리는 Loss를 증가시키고
학습을 통해 Loss를 줄일 것인데

00:23:57.051 --> 00:24:04.375
그 줄어드는 Loss의 량이 "조금 잘못된 것"이던  "많이 잘못된 것"
이던 큰 차이가 없을 것입니다.

00:24:04.375 --> 00:24:06.268
제가 좀 개략적으로 말씀드리긴 했지만

00:24:06.268 --> 00:24:13.597
둘 중 어떤 loss를 선택하느냐는 우리가 에러에 대해
얼마나 신경쓰고 있고, 그것을 어떻게 정량화 할 것인지에 달려있습니다.

00:24:13.597 --> 00:24:17.938
그리고 이 문제는 실제 여러분들이 손실함수를 만들때
고려해야만 하는 것입니다.

00:24:17.938 --> 00:24:22.770
왜냐하면 손실 함수라는 것이 여러분이 여러분들의 알고리즘에게
"어떤 에러를 내가 신경쓰고 있는지"

00:24:22.770 --> 00:24:26.267
그리고 "어떤 에러가 트레이드오프 되는 것인지" 를 알려주는 것입니다.

00:24:26.267 --> 00:24:30.407
그러니 실제로는 여러분들의 문제에 따라서 손실함수를
잘 설계하는 것은 엄청 중요하다고 할 수 있습니다.

00:24:32.315 --> 00:24:40.962
여기 Numpy 코드가 있습니다. 아마 여러분들도 첫 과제에서
이처럼 구현해야 할 것입니다.

00:24:40.962 --> 00:24:48.768
여기서 말씀드리고 싶었던건 Numpy를 사용하면 코드 몇줄이면
이 손실 함수를 코딩할 수 있다는 것입니다.

00:24:48.768 --> 00:24:50.926
여기 재미있는 기법을 하나 볼 수 있습니다.

00:24:50.926 --> 00:24:57.856
max로 나온 결과에서 정답 클래스만 0으로 만들어 주는 것이죠
(margin[y] = 0)

00:24:57.856 --> 00:25:06.069
이것은 굳이 전체를 순회할
필요가 없게 해주는 일종의 vectorized 기법입니다.

00:25:06.069 --> 00:25:09.854
전체 합을 구할때 제외하고 싶은 부분만 0으로 만들어줍니다.

00:25:09.854 --> 00:25:13.315
아마 과제를 할 때 아주 유용할 것입니다.

00:25:13.315 --> 00:25:17.106
자 이제 손실 함수에 대한 또 다른 질문이 있습니다.

00:25:17.106 --> 00:25:24.139
운이 좋게도 W가 0인 정답을 찾았다고 해 봅시다. 잃은 것이
전혀 없는 것이고, 여러분이 이긴 것입니다!

00:25:24.139 --> 00:25:32.390
그렇다면 여기서 질문입니다. 이렇게 Loss가 0이 되게 하는
W가 유일하게 하나만 존재하는 것일까요?

00:25:33.251 --> 00:25:34.271
- [학생]

00:25:34.271 --> 00:25:37.444
맞습니다. 다른 W도 존재합니다.

00:25:37.444 --> 00:25:43.976
특히나 좀 전에도 언급했듯이 W의 스케일은 변합니다.

00:25:43.976 --> 00:25:52.978
그렇다면 W에 두배를 한다고 해도 변하지 않을 것입니다.
(double double U 니까 quad U인가요?, 모르겠네요)

00:25:52.978 --> 00:25:54.110
[웃음]

00:25:54.110 --> 00:25:56.601
어쨋든 그 W도 역시 Loss가 0 이겠죠

00:25:56.601 --> 00:25:58.568
그래서 이것의 구체적인 예로서,

00:25:58.568 --> 00:26:00.066
좋아하는 예제로 돌아갈 수 있습니다.

00:26:00.066 --> 00:26:01.184
어쩌면 숫자를 통해 일할 수도 있습니다.

00:26:01.184 --> 00:26:02.351
나중에 조금,

00:26:02.351 --> 00:26:10.583
만약 여러분에게 W와 2W가 있다면, 정답 스코어 와 정답이 아닌
스코어의 차이의 마진(margins)또한 두배가 될 것입니다.

00:26:10.583 --> 00:26:14.521
그러니 모든 마진(margins)이 이미 1보다 더 크다면,
우리가 두배를 한다고 해도

00:26:14.521 --> 00:26:18.857
여전히 1보다 클 것이고 Loss가 0 일 것입니다.

00:26:20.180 --> 00:26:24.572
여기서 아주 흥미로운 점이 있습니다.

00:26:24.572 --> 00:26:29.045
손실 함수 라는 것이. 분류기에게 우리는 어떤 W를 찾고 있고
어떤 W에 신경쓰고 있는지를 말해주는 것이라면

00:26:29.045 --> 00:26:31.795
이것은 조금 이상합니다.
"불일치" 하는 점이 있습니다.

00:26:31.795 --> 00:26:39.112
다양한 W중 Loss가 0인 것을 선택하는 것은 모순입니다.

00:26:40.099 --> 00:26:45.303
왜냐하면 여기에서는 오직 데이터의 loss에 대해서만
신경쓰고 있고

00:26:45.303 --> 00:26:52.239
그리고 분류기에게 트레이닝 데이터에 꼭 맞는 W를
찾으라고 말하는 것 과 같습니다.

00:26:52.239 --> 00:26:56.465
하지만 실제로 우리는 트레이닝 데이터에 얼마나 꼭
맞는지는 전혀 신경쓰지는 않습니다.

00:26:56.465 --> 00:27:01.553
기계학습의 핵심은, 트레이닝 데이터를 이용해서
어떤 분류기를 찾는 것인데

00:27:01.553 --> 00:27:04.222
그 분류기는 테스트 데이터에 적용할 것이기 때문입니다.

00:27:04.222 --> 00:27:06.858
그러니 우리는 트레이닝 데이터의 성능에는
관심이 있는 것이 아니라

00:27:06.858 --> 00:27:10.928
우리는 테스트 데이터에서의 성능에 관심이 있는 것입니다.

00:27:10.928 --> 00:27:16.176
그러니 분류기에게 트레이닝 데이터의 Loss에만 신경쓰라고 한다면

00:27:16.176 --> 00:27:20.307
아마 좋지 않은 상황이 벌어질 것입니다.

00:27:20.307 --> 00:27:24.079
아마 분류기가 이해할 수 없는 행동을 할 수도 있습니다.

00:27:24.079 --> 00:27:27.786
좀 더 구체적인 예를 들어 보겠습니다.

00:27:27.786 --> 00:27:32.918
하지만 지금의 예는, 지금까지 배웠던 선현 분류기에 대한 것은 아니고
기계학습에서 다루는 좀 더 일반적인 개념이라 보시면 됩니다.

00:27:32.918 --> 00:27:35.815
여기 파란 점의 데이터 셋이 있습니다.

00:27:35.815 --> 00:27:39.827
이제 우리가 할 일은 어떤 곡선을 가지고
저 파란색 점들에 피팅시키는 것입니다.

00:27:39.827 --> 00:27:44.532
우리가 분류기에게 유일하게 말할 수 있는 것은, 그저
트레이닝 데이터에 핏 하게 하라고 말하는 것입니다.

00:27:44.532 --> 00:27:49.647
그러면 분류기는 모든 트레이닝 데이터를 완벽하게 분류해
내기 위해서 구불구불한 곡선을 만들 것입니다.

00:27:49.647 --> 00:27:53.519
하지만 이러면 안좋습니다. 왜냐하면 이 상황에서는
"성능" 에 대해서 전혀 고려하지 않았기 때문입니다.

00:27:53.519 --> 00:27:56.329
우린 항상 테스트 데이터의 성능을 고려해야 합니다.

00:27:56.329 --> 00:28:00.710
만약 새로운 데이터가 들어오게 되면

00:28:00.710 --> 00:28:03.872
앞서 만든 구불구불한 곡선은 완전히 틀리게 됩니다.

00:28:03.872 --> 00:28:09.334
사실 우리가 의도했던건 초록색 선인 것입니다.

00:28:09.334 --> 00:28:15.171
완벽하게 트레이닝 데이터에 핏한
복잡하고 구불 구불한 곡선을 원한 것이 아닌 것입니다.

00:28:15.171 --> 00:28:19.232
이는 기계학습에서 가장 중요한 문제 입니다.

00:28:19.232 --> 00:28:22.816
그리고 보통 이를 해결하는 방법을 통틀어
Regularization이라 합니다.

00:28:22.816 --> 00:28:26.443
손실 함수에 항을 하나 추가합니다.

00:28:26.443 --> 00:28:30.255
"Data Loss Term"에서는 분류기가 트레이닝 데이터에 핏하게 하고

00:28:30.255 --> 00:28:36.057
또한, 보통 손실 함수에 "Regularization term"을 추가하는데

00:28:36.057 --> 00:28:40.691
이는 모델이 좀 더 단순한 W를 선택하도록 도와줍니다.

00:28:40.691 --> 00:28:45.992
"단순하다" 라는 개념은 우리가 해결해야 할 문제나
모델에 따라 조금씩 달라집니다.

00:28:47.925 --> 00:28:52.868
과학 계에서 널리 쓰이는 "오컴의 면도날" 이라는 말이 있습니다.

00:28:52.868 --> 00:28:59.158
만약 여러분들에게 다양한 가설들을 가지고 있고,
그 가설들 모두가 어떤 현상에 대해 설명 가능하다면

00:28:59.158 --> 00:29:01.039
그럼 여러분은 일반적으로 "더 단순한 것" 을 선호해야 한다는 것입니다.

00:29:01.039 --> 00:29:06.801
왜냐하면 좀 "더 일반적인(더 단순한)" 것이
미래1에 일어날 현상을 잘  설명할 가능성이 더 높기 때문입니다.

00:29:06.801 --> 00:29:12.538
 그리고 기계학습에서는 이런 류의 직관을 써먹기 위해서
"Regularization penalty"라는 것을 만들어 냈습니다.

00:29:12.538 --> 00:29:15.121
Regularization은 보통 R로 표기합니다.

00:29:16.312 --> 00:29:20.409
그렇게 되면, 일반적인 손실 함수의 형태는
두가지 항을 가지게 됩니다.

00:29:20.409 --> 00:29:22.417
Data loss와 Regularization loss입니다.

00:29:22.417 --> 00:29:27.200
그리고 하이퍼파라미터인 람다(lambda)도 생겼습니다.
두 항 간의 트레이드오프입니다.

00:29:27.200 --> 00:29:31.054
지난 강의에서 하이퍼파라미터와 크로스벨리데이션을 배웠습니다.

00:29:31.054 --> 00:29:39.363
여기 Regularization의 하이퍼파라미터 람다는 실제로 여러분들이
모델을 훈련시킬 때 고려해야 할 중요한 요소 중 하나입니다.

00:29:40.229 --> 00:29:41.062
질문 있나요?

00:29:42.097 --> 00:29:48.846
- [학생 질문]

00:29:50.685 --> 00:29:51.941
질문은 바로

00:29:51.941 --> 00:29:58.072
Wx + lambda R 이란 것이 도대체 뭐길래 구불구불한 곡선을
직선으로 바꿔 준다는 것입니까? 라는 것입니다.

00:29:59.912 --> 00:30:03.550
사실 그 부분을 깊에 다루려면 너무 오래걸려서
여기에서는 언급하려 하지 않았습니다.

00:30:03.550 --> 00:30:09.830
하지만 짐작해 볼 수 있습니다. 여러분들에게 회귀문제가 있습니다.
일종의 다항식 기저 함수로 나타낼 수 있겠죠

00:30:09.830 --> 00:30:15.775
일반적으로 모델은 고차 다항식을 이용해서 문제를 풀려 할 것입니다.

00:30:15.775 --> 00:30:25.569
여기에 어떤 regression term을 추가하면 모델이 데이터를
핏 할 떄 저차 다항식을 더 선호하도록 하게 하는 것입니다.

00:30:25.569 --> 00:30:29.021
그러니 여러분은 Regularization의 두 가지
역할에 대해 생각해 볼 수 있습니다.

00:30:29.021 --> 00:30:32.897
하나는 여러분의 모델이 더 복잡해 지지 못하도록 하는 것이고

00:30:32.897 --> 00:30:40.846
또는 모델에 soft penalty를 추가하는 것으로 보는 것입니다.
모델은 여전히 더 복잡한 모델이 될 가능성이 있는 것입니다.

00:30:40.846 --> 00:30:43.112
이 다항식의 예라면, 더 복잡한 차수에도 접근할 수 있는 것이지요

00:30:43.112 --> 00:30:51.316
하지만 이 soft한 제약을 하나 추가하면, "만약 너가 복잡한 모델을 계속
쓰고싶으면, 이 penalty를 감수해야 할 거야!" 라는 것과 같습니다.

00:30:51.316 --> 00:30:55.282
이것으로 인해 완전한 선형 분류문제가 되진 않겠지만

00:30:55.282 --> 00:31:01.691
많은 사람들이 "Regularization"에 대해 이런 식으로 떠올립니다.

00:31:02.731 --> 00:31:06.917
실제로 Regularization에는 여러 종류가 있습니다.

00:31:06.917 --> 00:31:11.022
가장 보편적인 것은 L2 Regularization입니다.
Weight decay라고도 하죠.

00:31:11.022 --> 00:31:13.905
이 외에도 다양한 것이 많습니다.

00:31:13.905 --> 00:31:19.470
L2 Regularization은 가중치 행렬W에 대한
Euclidean Norm입니다.

00:31:19.470 --> 00:31:21.892
간혹 squared norm이라고도 하죠

00:31:21.892 --> 00:31:26.738
또는 1/2 * squared norm 을 사용하기도 합니다.
미분이 더 깔끔해집니다.

00:31:26.738 --> 00:31:32.650
하지만 L2 Regularization의 주요 아이디어는
가중치 행렬 W의 euclidean norm에 패널티를 주는 것입니다.

00:31:32.650 --> 00:31:38.957
그리고 L1 regularization도 보게 될 것인데,
이는 L1 norm으로 W에 패널티를 부과하는 것입니다.

00:31:38.957 --> 00:31:46.401
L1 Regularization을 하면 행렬 W가 희소행렬이 되도록 합니다.

00:31:46.401 --> 00:31:52.744
그리고 Elastic net regularization도 있습니다.
L1과 L2를 짬뽕해놓은 것이죠

00:31:52.744 --> 00:32:00.004
간혹 Max norm regularization도 보게 될 것입니다.
L1, L2 대신에 max norm을 쓰는 것이죠

00:32:01.119 --> 00:32:07.374
하지만 이런 regularization은 딥러닝에서만 쓰는 것이 아니라
많은 기계학습 분야를 통틀어서 자주 사용하는 것입니다.

00:32:07.374 --> 00:32:10.997
심지어는 더 광범위하게 최적화 할 수도 있습니다.

00:32:10.997 --> 00:32:17.138
Regularization 기법 중 특히나 딥러닝에 관련된 기법들을
앞으로 배우게 될 것입니다.

00:32:17.138 --> 00:32:25.157
예를 들어, 앞으로 배울 Dropout이나 Batch Normalization
, Stochastic depth와 같은 최근 아주 쩌는 것들이죠

00:32:25.157 --> 00:32:37.061
Regularization은 모델이 트레이닝 데이터셋에 완벽히
핏 하지 못하도록 모델의 복잡도에 패널티를 부여하는 방법입니다.

00:32:37.061 --> 00:32:38.306
질문 있나요?

00:32:38.306 --> 00:32:41.889
[말하는 학생]

00:32:44.858 --> 00:32:50.186
질문은, "L2 Regularization이 모델이 복잡한지 아닌지를
어떻게 알(측정) 수 있냐" 는 것입니다.

00:32:50.186 --> 00:32:54.202
고맙게도 다음에 할 내용이 바로 그것입니다.

00:32:55.437 --> 00:33:00.058
여기 한 예시가 있습니다. 트레이닝 데이터 x가 있고
서로 다른 두개의 W가 있습니다.

00:33:00.058 --> 00:33:07.157
x는 4줄짜리 벡터이고, 여기에 두개의 서로 다른 W에 대해
생각해 볼 수 있겠습니다. x = [1 1 1 1]

00:33:07.157 --> 00:33:10.367
하W중 하나는 처음에만 1이 있고 나머지 세 원소는 0입니다.
w1 = [1 0 0 0]

00:33:10.367 --> 00:33:14.191
다른 하나는 원소가 모두 0.25입니다.
 w2 = [0.25 0.25 0.25 0.25]

00:33:14.191 --> 00:33:19.702
이걸 가지고 Linear classification을 할때
우리는 x와 w의 내적을 구합니다.(dot product)

00:33:19.702 --> 00:33:24.747
Linear classification의 관점에서 w1와 w2는 같습니다.

00:33:24.747 --> 00:33:28.302
왜냐하면 x와의 내적이 서로 같기 때문이죠.

00:33:28.302 --> 00:33:34.383
여기서 문제는, w1, w2중 L2 regression이
더 선호하는것은 어떤 것일까요?

00:33:36.052 --> 00:33:41.030
L2 regression은 w2를 더 선호할 것입니다.
왜냐면 L2 regression에서는 w2가 더 norm이 작기 때문이죠

00:33:41.030 --> 00:33:49.440
그러니 L2 Regression은 분류기의 복잡도를 상대적으로 w1와
w2중 어떤 것이 더 coarse한지를 측정합니다. (값이 매끄러워야함)

00:33:49.440 --> 00:34:01.920
Linear classification에서 W가 의미하는 것은, "얼마나 x가
Output Class와 닮았는지" 입니다.

00:34:01.920 --> 00:34:09.080
그러니 L2 Regularization이 말하고자 하는것은
x의 모든 요소가 영향을 줬으면 하는 것입니다.

00:34:09.080 --> 00:34:14.585
그러니 변동이 심한 어떤 입력 x가 있고
그 x의 특정 요소에만 의존하기 보다

00:34:14.585 --> 00:34:22.059
모든 x의 요소가 골고루 영향을 미치길 원한다면,
L2 Regularization을 통해 더 강인해 질 수 있을 것입니다.

00:34:22.060 --> 00:34:26.839
반면 L1 Regularization의 경우에는 정 반대입니다.

00:34:26.839 --> 00:34:32.946
L1 Regularization을 쓰게 되면 W2보다는
W1을 더 선호하게 됩니다.

00:34:32.946 --> 00:34:35.595
L1 Regularization은 "복잡도"를 다르게 정의합니다.

00:34:35.595 --> 00:34:46.080
L1 Regularization은 가중치 W에 0의 갯수에 따라
모델의 복잡도를 다룹니다.

00:34:46.080 --> 00:34:51.917
그러니 "복잡도" 을 어떻게 정의하느냐, 그리고
L2 Regularization은 "복잡도"을 어떻게 측정하느냐는

00:34:51.917 --> 00:34:54.196
우리가 어떤 문제를 가지고 있으냐에 따라 다릅니다.

00:34:54.196 --> 00:34:58.921
그러니 여러분이 어떤 문제가 있고, 어떤 모델이 있고 데이터가 있을때

00:34:58.921 --> 00:35:02.837
여러분은 이 문제에서 "복잡하다"는 것을
어떻게 정의할 지를 반드시 고민해야 할 것입니다.

00:35:03.921 --> 00:35:04.788
질문 있나요?

00:35:04.788 --> 00:35:09.129
- [학생]

00:35:09.129 --> 00:35:10.385
네 맞습니다.

00:35:10.385 --> 00:35:13.830
w1과 w2의 경우에는 L1의 값이 같습니다.

00:35:15.193 --> 00:35:21.546
하지만 여러분은 L1 Regularization이 선호하는 w1를
손쉽게 만들어 볼 수 있습니다.

00:35:21.546 --> 00:35:26.908
L1에 대한 일반적인 직관은
"일반적으로 L1은 sparse한 solutions을 선호한다"는 것입니다.

00:35:26.908 --> 00:35:35.016
그리고 이것은 W의 요소 중 대부분이 0이 되게 할 것입니다.

00:35:35.016 --> 00:35:40.191
그렇게 때문에 L1이 "복잡하다"고 느끼고 측정하는 것은
0이 아닌 요소들의 갯수가 될 수 있습니다.

00:35:40.191 --> 00:35:45.682
반면 L2의 경우에는 W의 요소가 전체적으로 퍼져있을 때
"덜 복잡하다" 라고 생각하게 됩니다.

00:35:45.682 --> 00:35:48.920
그러니 선택은 여러분들의 데이터와 문제에 달려 있습니다.

00:35:48.920 --> 00:35:54.584
좀 더 나아가서, 여러분이 Bayesian에 대해 잘 안하면
L2 Regularization을 사용하다는 것을

00:35:54.584 --> 00:35:58.897
parameter vector로 Gaussian prior를 쓰는
MAP inference로 볼 수도 있다는 것입니다.

00:35:58.897 --> 00:36:05.343
해당 하는 내용이 CS229의 과제에 있었던 것으로 기억하지만
이 강의에서는 더이상 다루지는 않을 것입니다.

00:36:05.343 --> 00:36:11.400
지금 우리는 multi-class SVM Loss에 대해
깊게 알아보고 있는 중입니다.

00:36:11.400 --> 00:36:12.783
질문 있나요?

00:36:12.783 --> 00:36:32.648
[학생 질문]

00:36:33.982 --> 00:36:39.798
질문은, Regularization된다고
Hypothesis class가 변하지 않을 것이라는 것입니다.

00:36:39.798 --> 00:36:44.036
그리고 Linear classifier 라는 것이 변하지 않을 것이라는
것입니다.

00:36:44.036 --> 00:36:50.038
이 Polynomial regression의 예는 확실이
Linear regression은 아닙니다.

00:36:50.038 --> 00:36:56.826
입력의 차수가 증가하는 상황에서의 Linear regression으로
볼 수는 있습니다.

00:36:56.826 --> 00:37:05.802
이 경우에는 우리가 많은 polynomial coefficients를
사용하고 싶지는 않다는 것을 의미하는 것입니다.

00:37:05.802 --> 00:37:07.385
이런 식으로 생각해 보시면 될 것 같습니다.

00:37:07.385 --> 00:37:09.290
여러분이 polynomial regression을 한다고 했을때

00:37:09.290 --> 00:37:17.963
f(x)=A0 * 1 + A1 * x + A2 * x^2 + A3 * x^3
와 같은 식으로 나타낼 수 있겠죠

00:37:17.963 --> 00:37:23.093
이 경우 우리가 가진 parameters는 A집합이 되겠습니다.

00:37:24.211 --> 00:37:28.190
A에 penalty를 준다는 것은 polynomial의 차원이
더 적어지도록 하는 것입니다.

00:37:28.190 --> 00:37:31.491
Polynomial regression의 경우가 아니라면
실제로 A의 형태로 파라미터가 생기진 않을 것입니다.

00:37:31.491 --> 00:37:34.725
여러분이 사용하고 싶은 다른 파마미터를 설정하게 될 것입니다.

00:37:34.725 --> 00:37:36.364
그러나 그것은 일반적인 생각입니다,

00:37:36.364 --> 00:37:44.285
hypothesis class 중에 더 간단한 것을 선택하기 위해서
우리는 model에 Penalty를 주는 것입니다.

00:37:45.229 --> 00:37:50.340
아직 헷갈리면 개인적으로 다시 질문해 주시기 바랍니다.

00:37:50.340 --> 00:37:56.349
지금까지 Multi-class SVM Loss에 대해 알아보았습니다.
그리고 부차적으로 또 하나가 있습니다.

00:37:56.349 --> 00:38:03.097
지금까지 본 것은 SVM Loss를 Multi class로 확장시킨
아주 일반적인 손실함수일 뿐입니다.

00:38:03.097 --> 00:38:06.596
여러 문헌을 찾아보게 되면 몇가지 다른 공식들도 존재합니다.

00:38:06.596 --> 00:38:13.813
하지만, 적어도 딥러닝에서는 그런 여러가지 손실함수들이
사실은 거의 비슷하게 동착합니다.

00:38:13.813 --> 00:38:19.949
그렇기 때문에, 이 수업에서는 지금까지 배웠던
multi-class SVM loss만 가지고 이야기할 것입니다.

00:38:21.061 --> 00:38:25.158
하지만 당연히 여러분이 생각해볼만한 여러 다양한
손실 함수들이 존재합니다.

00:38:25.158 --> 00:38:30.603
multi-class SVM loss 외에도 인기있는 것이 하나 있습니다.

00:38:31.761 --> 00:38:37.769
딥러닝에서 자주쓰는 Multinomial logistic
regression, 즉 softmax입니다.

00:38:39.405 --> 00:38:43.222
사실 딥러닝에서는 이걸 더 많이 씁니다.

00:38:43.222 --> 00:38:48.127
하지만 몇가지 이유가 있어 두번째로 소개해 드립니다.

00:38:48.127 --> 00:38:55.096
multi-class SVM loss에서 우리는 스코어 자체에 대한
해석은 고려하지 않았습니다.

00:38:55.096 --> 00:39:02.670
어떤 분류문제가 있고 어떤 모델 F가 각 클래스에
해당하는 10개의 숫자를 출력할때면

00:39:02.670 --> 00:39:07.787
mulfi-class SVM의 경우에 우리는 그 스코어 자체는
크게 신경쓰지 않았습니다.

00:39:07.787 --> 00:39:13.497
우린 단지 정답 클래스가 정답이 아닌 클래스들 보다 더 높은
스코어를 내기만을 원했죠

00:39:13.497 --> 00:39:17.712
그 이상, 스코어 자체가 실제로 의미하는 것에는
관심이 없었습니다.

00:39:17.712 --> 00:39:27.668
하지만 Multinomial Logistic regression의 손실함수는
스코어 자체에 추가적인 의미를 부여합니다.

00:39:27.668 --> 00:39:33.907
그리고 특히, 저 수식을 이용해서 스코어를 가지고 클래스 별
확률 분포를 계산하게 될 것입니다.

00:39:33.907 --> 00:39:37.324
여기에서는 softmax라고 불리는 함수를 쓸 것입니다.

00:39:37.324 --> 00:39:43.192
스코어를 전부 이용하는데, 스코어들에 지수를 취해서
양수가 되게 만듭니다.

00:39:43.192 --> 00:39:46.540
그리고 그 지수들의 합으로 다시 정규화 시킵니다.

00:39:46.540 --> 00:39:53.053
그래서 softmax 함수를 거치게 되면
우리는 결국 확률 분포를 얻을 수 있고

00:39:53.053 --> 00:39:55.792
그것은 바로 해당 클래스일 확률이 되는 것입니다.

00:39:55.792 --> 00:39:58.193
 확률이기 때문에 0에서 1 사이의 값이고

00:39:58.193 --> 00:40:02.287
모든 확률들의 합은 1이 됩니다.

00:40:03.954 --> 00:40:07.169
이제 한번 해석을 해봅시다.

00:40:07.169 --> 00:40:12.020
이게 우리가 스코어를 가지고 계산한
확률 분포가 있습니다.

00:40:12.020 --> 00:40:17.138
이제 이 확률값을 실제 값과 비교해 볼 것입니다.

00:40:17.138 --> 00:40:26.904
만약 이미지가 고양이라면
실제 고양이 일 확률은 1이 됩니다.

00:40:26.904 --> 00:40:29.754
그리고 나머지 클래스의 확률은 0이 됩니다.

00:40:29.754 --> 00:40:35.574
내그러니 우리가 지금 하고자 하는 것은
softmax에서 나온 확률이

00:40:35.574 --> 00:40:40.671
정답 클래스에 해당하는 클래스의 확률을 1로 나타내게 하는 것입니다.

00:40:40.671 --> 00:40:51.102
이런 식은 다양하게 사용될 수 있습니다. 예를 들어
두 분포 간의 KL divergence라던가

00:40:51.102 --> 00:40:53.221
아님 이 식은 MLE로 볼 수도 있습니다.

00:40:53.221 --> 00:41:00.839
하지만 결국 우리가 원하는 것은 정답 클래스에 해당하는
클래스의 확률이 1에 가깝게 계산되는 것입니다.

00:41:00.839 --> 00:41:06.389
그렇게 되면 Loss는 "-log(정답클래스확률)" 이 될 것입니다.

00:41:06.389 --> 00:41:09.707
여기에 이것저것 들어가서 헷갈릴 수도 있지만

00:41:09.707 --> 00:41:13.524
한번 잘 생각해보면 우린 지금
확률이 1이 되길 원하고 있습니다.

00:41:13.524 --> 00:41:17.071
그리고 log는 단조 증가 함수이죠, 이런식으로 증가하죠

00:41:17.071 --> 00:41:25.604
그리고 log를 최대화시키는 것이 그냥 확률값을 최대화 시키는 것
보다 쉽습니다. 그러니 우리는 log를 씁니다.

00:41:25.604 --> 00:41:32.599
log가 단조증가함수 라고 했었죠 그러니 정답 클래스인,  log P
를 최대화 시키는건, lop P가 높았으면 좋겠다는 것인데

00:41:32.599 --> 00:41:40.051
그런데 손실 함수는 "얼마나 좋은지" 가 아니라 "얼마나 구린지"
를 측정하는 것이기 때문에 log에 마이너스를 붙힙니다.

00:41:40.051 --> 00:41:46.148
이제 SVM의 손실함수는 -log(P(정답클래스)) 로
나타내게 됩니다.

00:41:48.909 --> 00:41:51.322
요약을 해보자면

00:41:51.322 --> 00:41:57.575
스코어가 있으면, softmax를 거치고, 나온 확률 값이
-log를 추가하면 됩니다.

00:42:01.697 --> 00:42:05.043
이제 이게 어떻게 생겼는지 구체적인 예시로
확인해 보겠습니다.

00:42:05.043 --> 00:42:14.486
다시 고양이 예제로 돌아가 봅시다. 여기 Linear classifier
의 출력으로 나온 스코어가 있습니다.

00:42:14.486 --> 00:42:18.712
이 스코어는 이전에 SVM  Loss에서의 예제와 같은 값입니다.

00:42:18.712 --> 00:42:25.422
하지만 이제는 스코어 자체를 Loss로 쓰기보다는
이제 스코어를 지수화 시킬 것입니다.

00:42:25.422 --> 00:42:26.990
그래서 그들은 모두 긍정적입니다,

00:42:26.990 --> 00:42:31.025
그리고 합이 1이 되도록 정규화 시켜 줍니다.

00:42:31.025 --> 00:42:35.788
그리고 정답 스코어에만 -log를 씌여줍니다.

00:42:36.643 --> 00:42:43.823
이걸 softmax라고 합니다. 또는 다항 로지스틱 회귀라고도 하죠.
(multinomial logistic regression)

00:42:45.496 --> 00:42:50.750
이전에 여러분이 직관을 얻을 수 있도록
 multi-class SVM Loss 몇 가지를 던졌었는데요.

00:42:50.750 --> 00:42:57.360
Softmax loss를 이해하는데도 그 질문이 도움이 될 것입니다.

00:42:57.360 --> 00:42:58.614
그럼 질문은

00:42:58.614 --> 00:43:02.697
softmax loss의 최댓값과 최솟값을 얼마일까요?

00:43:04.984 --> 00:43:09.720
여기 log도 있고 합치는 것도 있고 해서 좀
헷갈릴수도 있습니다.

00:43:11.298 --> 00:43:15.430
정답은 바로 Loss의 최솟값은 0 이고 최댓값은 무한대입니다.

00:43:15.430 --> 00:43:24.467
확률 분포를 한번 생각해 보자면, 우리는 정답 클래스의 확률은 1이
되길 원하고 정답이 아닌 클래스는 0 이 되길 원합니다.

00:43:24.467 --> 00:43:31.366
이런 식으로 생각해보면, log안에 있는 어떤 값은
결국 1이 되어야 하는 것입니다.

00:43:33.662 --> 00:43:40.917
정답 클래스에 대한 Log 확률이기 때문에
Log(1) = 0 이고, -log(1) 또한 0입니다.

00:43:41.893 --> 00:43:46.515
그러므로 고양이를 완벽히 분류했다면
Loss는 0이 될 것입니다.

00:43:46.515 --> 00:43:53.582
그렇다면 Loss가 0이 되려면 실제 스코어는 어떤 값이어야 할까요?

00:43:55.963 --> 00:44:01.572
아마 정답 스코어는 극단 적으로 높아야 할 것입니다.
거의 무한대에 가깝게 말이죠

00:44:01.572 --> 00:44:06.098
여기에서는 지수화를 하고 정규화를 하기 때문에

00:44:06.098 --> 00:44:17.509
우리가 확률 1(정답) 과 0(그외) 를 얻으려면, 정답 클래스의 스코어는
+무한대 가 되어야 하고, 나머지는 -무한대 가 되어야 합니다.

00:44:17.509 --> 00:44:24.108
컴퓨터는 무한대 계산을 잘 못하기 때문에,
Loss가 0인 경우는 절대 없을 것입니다.(유한 정밀도 때문에)

00:44:24.108 --> 00:44:29.223
하지만 이론적 해석을 가미하면
0 은 "이론적으로 최소 Loss이다" 라고 보면 됩니다.

00:44:29.223 --> 00:44:31.607
최대 손실은 최댓값이 없습니다.

00:44:31.607 --> 00:44:39.483
만약 정답 클래스의 확률이 0이고, 거기 -log를 취하면
[-log(0)]

00:44:39.483 --> 00:44:46.283
log(0)는 음의 무한대가 되고
따라서 -log(0)는 양의 무한대가 됩니다.

00:44:46.283 --> 00:44:47.334
정말 안좋은 경우이겠죠

00:44:47.334 --> 00:44:58.563
하지만 이러한 경우 또한 발생하지는 않을 것입니다. 왜냐하면
확률이 0이 되려면 e^syi가 0이 되어야 하는데

00:44:58.563 --> 00:45:01.630
그게 가능한 경우는 정답 클래스의 스코어가
음의 무한대일 일 때 뿐이기 떄문입니다.

00:45:01.630 --> 00:45:07.117
다시한번 말씀드리자만 "유한 정밀도" 를 가지고는
최댓값(무한대) 최솟값(0)에 도달할 수는 없습니다.

00:45:08.863 --> 00:45:14.340
또한 multi-class SVM 손실함수를 이야기할때
디버깅을 할 수 있는 방법에 대해서는 말씀드렸는데요

00:45:14.340 --> 00:45:16.401
softmax도 같습니다.

00:45:16.401 --> 00:45:21.287
만약 S가 모두 0 근처에 모여있는 작은 수일때
Loss는 어떻게 될까요?

00:45:21.287 --> 00:45:22.292
정답?

00:45:22.292 --> 00:45:27.045
- [학생]

00:45:27.045 --> 00:45:33.352
맞습니다.
-log(1/C) 가 되겠죠

00:45:33.352 --> 00:45:38.079
log는 분모와 분자를 뒤집을 수 있으니까
-log(1/C)는 log(C)가 됩니다.

00:45:38.079 --> 00:45:43.977
softmax를 사용할 때 첫 번째 interation에서 해볼만한
아주 좋은 디버깅 전략입니다.

00:45:43.977 --> 00:45:47.894
log(c)가 아니면 뭔가 잘못된 것입니다.

00:45:50.051 --> 00:45:54.600
이제 지금까지 배운 두 손실함수를 한번
비교해 보겠습니다.

00:45:54.600 --> 00:45:57.532
Linear classification의 설정은 둘다 같은 조건입니다.

00:45:57.532 --> 00:46:02.072
행렬 W와 입력을 못하는 것은 둘다 같습니다.

00:46:02.072 --> 00:46:09.327
다만 두 손실 함수의 차이점은 바로 "얼마나 구린지" 를 측정하기 위해
스코어를 해석하는 방식이 조금 다르다는 것입니다.

00:46:09.327 --> 00:46:17.138
SVM에서는 정답 스코어와, 정답이 아닌 스코어 간의
마진(margins)을 신경썼습니다.

00:46:17.138 --> 00:46:26.663
반면 softmax (crossentropy) 는 확률을 구해서
-log(정답클래스) 에 신경을 씁니다.

00:46:26.663 --> 00:46:33.216
간혹 이것을....
아니다 이부분은 건너 뛰겠습니다.

00:46:33.216 --> 00:46:34.917
[웃음]

00:46:34.917 --> 00:46:40.854
두 손실 함수 간의 차이에 대한 흥미로운 질문이 하나 있습니다.

00:46:40.854 --> 00:46:54.042
[어떤 얘기 하다가 다른 예시로 돌림]
여기 있는 예제는 무시하세요

00:46:54.042 --> 00:46:59.814
multi-class SVM loss의 예시를 다시 생각해보면

00:46:59.814 --> 00:47:06.293
car클래스에서 car의 스코어가 다른 클래스보다
훨씬 높았습니다.

00:47:06.293 --> 00:47:11.246
그래서 car스코어를 조금 바꾼다고 해서
 SVM Loss가 변하거나 하진 않았죠

00:47:11.246 --> 00:47:18.359
왜냐면 SVM loss는 오직 정답과 그 외 클래스의 마진이 얼마나
되는지 에만 관심이 있기 때문입니다.

00:47:18.359 --> 00:47:21.726
이런 점에서 softmax loss는 상당히 다릅니다.

00:47:21.726 --> 00:47:26.438
softmax는 언제나 확률은 1로 만드려고 노력할 것입니다.

00:47:26.438 --> 00:47:34.298
그러니, 정답 스코어가 충분히 높고, 다른 클래스
스코어가 충분히 낮은 상태에서도

00:47:34.298 --> 00:47:40.044
softmax는 최대한 정답 클래스에 확률을 몰아 넣으려고 할 것이고

00:47:40.044 --> 00:47:46.138
정답 클래스는 무한대로, 그 외의 클래스는
음의 무한대로 보내려 할 것입니다.

00:47:46.138 --> 00:47:49.968
그리고 그것은 두 손실 함수 간의 흥미로운 차이점 입니다.

00:47:49.968 --> 00:47:57.739
SVM의 경우에는 일정 선(margins)을 넘기만 하면 더이상
성능 개선에 신경쓰지 않습니다.

00:47:57.739 --> 00:48:03.838
반면 softmax는 더더더더더좋게 성능을 높이려 할 것입니다.

00:48:03.838 --> 00:48:07.378
두 손실 함수 간의 흥미로운 차이점인 것입니다.

00:48:07.378 --> 00:48:15.966
실제 딥러닝 애플리케이션에서 두 손실 함수 간의 성능 차이는
엄청나게 크진 않습니다만

00:48:15.966 --> 00:48:19.970
그렇긴 해도 차이를 알고 있는 것은 유용할 것입니다.

00:48:23.054 --> 00:48:26.176
자 이제 지금까지 한 것들을 정리해 보자면

00:48:26.176 --> 00:48:29.585
우선 우리에게 데이터 셋 x와 y가 있습니다.

00:48:29.585 --> 00:48:36.595
우선 입력 x로부터 스코어를 얻기 위해
Linear classifier를 사용 할 것입니다.

00:48:36.595 --> 00:48:48.954
softmax, svm loss와 같은 손실함수를 이용해서, 모델의 예측값이
정답 값에 비해 "얼마나 구린지"를 측정합니다.

00:48:48.954 --> 00:48:59.059
그리고 모델의 "복잡함" 과 "단순함" 을 통제하기 위해
손실 함수에 regularization term을 추가할 것입니다.

00:48:59.059 --> 00:49:03.966
지금까지 우리가 Supervised leraning이라 부르는 것에
관한 전반적인 개요를 배워 보았습니다.

00:49:03.966 --> 00:49:12.664
우리가 딥러닝에서 배울 내용은, 어떤 엄청 복잡한 함수 f를 정의하고

00:49:12.664 --> 00:49:19.645
그리고는 파라미터 값이 주어졌을때 알고리즘이 얼마나
"구리게" 동작하고 있는지 측정할 손실 함수를 작성하고

00:49:19.645 --> 00:49:24.260
그리고 모델이 복잡해 지는 것을 어떻게 막을지에 대한
Regularization term을 추가합니다.

00:49:24.260 --> 00:49:30.866
그리고 그걸 모두 합쳐서, 최종 손실 함수가 최소가 되게 하는
가중치 행렬이자 파라미터인 행렬W를 구하게 되는 것입니다.

00:49:30.866 --> 00:49:37.132
자 이제 다음 질문은, 실제로 어떻게 해야 하는 것일까요?
어떻게 실제 Loss를 줄이는 W를 찾을 수 있는 걸까요?

00:49:37.132 --> 00:49:40.461
이 질문은 우리를 "최적화" 라는 주제로 이끌어 줍니다.

00:49:40.461 --> 00:49:47.482
최적화를 하고 있다는걸 상상해보면,
우리가 엄청 큰 계곡을 걷고 있는 것 같습니다.

00:49:47.482 --> 00:49:54.183
여러분은 다양한 산과 계곡과 시내가 있는 엄청 큰
골짜기를 거닐고 있는 것입니다.

00:49:54.183 --> 00:50:00.729
그리고 "산"과 "계곡" 과 같은 풍경들이 바로
파라미터 W입니다.

00:50:00.729 --> 00:50:04.517
그리고 여러분이 이 골짜기를 돌아다니는 한 사람인 것이고,

00:50:04.517 --> 00:50:10.728
내가 있는 곳의 "높이" 가 바로 Loss 인 것입니다.
Loss는 W에 따라 변하게 되고, 우리는 W를 찾아야 합니다.

00:50:10.728 --> 00:50:14.181
여러분의 임무는 이곳을 돌아다니는 한 사람이 되어

00:50:14.181 --> 00:50:18.000
어떻게든 이 골짜기의 밑바닥을 찾아내는 것입니다.

00:50:18.000 --> 00:50:20.517
하지만 그런 문제들은 일반적으로 엄청 어렵습니다.

00:50:20.517 --> 00:50:27.379
만약 여러분이 엄청 똑똑해서 손실함수와 regularization
등 모든 것들의 속성 하나 하나를 다 분석해 냈다면

00:50:27.379 --> 00:50:35.509
어쩌면 제가 골짜기의 밑바닥으로 마법같이 순간이동할 수 있는
minimizer를 만들어낼 수도 있겠 습니다만

00:50:35.509 --> 00:50:44.609
하지만 실제로 NN을 사용하면  "예측 함수", "손실함수",
"Regularizer" 같은 것들이 엄청 크고 복잡해 져서

00:50:46.190 --> 00:50:52.017
어떤 명시적인 솔루션을 만들어내서 최적의 솔루션(minima)를
직접 얻어내는 것은 불가능 할 것입니다.

00:50:52.017 --> 00:50:55.485
그래서 실제로 우리는 다양한 "iterative한 방법"들을 씁니다.

00:50:55.485 --> 00:51:00.524
이 방법들은 임의의 지점에서 시작해서
점차적으로 성능을 향상시키는 방법입니다.

00:51:00.524 --> 00:51:06.985
우선, 가장 먼저 생각해 볼 수 있는 단순한 방법은
임의 탐색(random search) 입니다.

00:51:06.985 --> 00:51:14.963
임의로 샘플링한 W들을 엄청 많이 모아놓고 Loss를 계산해서
어떤 W가 좋은지를 살펴보는 것입니다.

00:51:14.963 --> 00:51:18.828
미리 말씀드리자면 정말 구린 알고리즘이고
여러분들은 절대로 이 방법은 쓰지 마셔야 합니다.

00:51:18.828 --> 00:51:23.323
하지만 한번쯤 "상상"해 볼 법한 방법이긴 합니다.

00:51:23.323 --> 00:51:30.813
실제로 해 볼수도 있긴 합니다.
임의 탐색으로 Linear Classfier을 학습시킬 수 있습니다.

00:51:30.813 --> 00:51:39.768
CIFAR-10에서 클래스는 10개이니까 임의 확률은 10%가 되고,
무작위 시행을 거치게 되면,

00:51:39.768 --> 00:51:45.645
소가 뒷걸음질 치는 격으로 어떤 W를 구해 볼 수 있는데
이 예시에서는 15%의 정확도를 보이는군요

00:51:45.645 --> 00:51:53.831
10개중 하나 찍는것 보단 좋지만, 최신 알고리즘의 성능
(SOTA)이 95%라는 점을 생각하면, 격차가 좀 많이 나죠

00:51:53.831 --> 00:52:00.677
실제로는 이렇게 하지 마시고 이런 방법도 "가능은 하다"
정도로만 알고 넘어가시면 되겠습니다.

00:52:00.677 --> 00:52:06.168
실제로 더 나은 전략은 지역적인 기하학적 특성을 이용하는 것입니다.
(local geometry)

00:52:06.168 --> 00:52:09.910
만일 여러분이 이 계곡을 걷고있는 사람이라면

00:52:09.910 --> 00:52:13.802
여러분이 계곡의 밑바닥이 어디인지 두 눈으로 확인할 수는
없을 것입니다.

00:52:13.802 --> 00:52:19.531
하지만 두 발로 느끼고 그곳의 지형을 파악할 수 있을 것입니다.

00:52:20.697 --> 00:52:24.145
제가 여기에 이렇게 서있다면 어떤 방향으로 가야
내려갈 수 있을까요?

00:52:24.145 --> 00:52:30.861
여러분은 두 발로 땅의 경사를 느끼고, 어느 방향으로 가야
내려갈 수 있을지를 알 수 있을 것입니다.

00:52:30.861 --> 00:52:36.260
이제 그 방향으로 한발자국 내딛고는 조금 걸어내려 가다가는,
다시 두 발로 느끼고 방향을 다시 찾아봅니다.

00:52:36.260 --> 00:52:41.526
이렇게 반복하다 보면 결국 여러분은  골짜기를
다 내려갈 수 있을 것입니다.

00:52:41.526 --> 00:52:50.195
이 알고리즘이 엄청 쉬워보이지만, 실제로 정말 잘 동작합니다.
만약 여러분이 세부 사항을 잘 파악한다면 말이죠

00:52:50.195 --> 00:52:57.028
이 방법은 우리가 NN이나 Linear classifer 같은 것들을 훈련시킬
때 일반적으로 사용하는 방법입니다.

00:52:57.028 --> 00:52:58.769
지금까지는 대략적인 감만 설명해 드린 것입니다.

00:52:58.769 --> 00:52:59.952
그렇다면 경사(slope)는 무엇일까요?

00:52:59.952 --> 00:53:07.673
미분 수업이 기억나시나요? 1차원 공간에서
경사(slope)는 어떤 함수에 대한 미분값입니다.

00:53:07.673 --> 00:53:12.969
1차원 함수 f가 있다고 해봅시다. f(x) = y
x를 입력으로 받으면, 출력은 어떤 커브의 높이겠죠

00:53:12.969 --> 00:53:16.460
곡선의 일부를 구하면 기울기를 계산할 수 있습니다.

00:53:16.460 --> 00:53:19.717
이제 어떤 점(x)에서의 경사, 즉 도함수(derivative)를 계산해보면

00:53:19.717 --> 00:53:29.798
작은 스텝 , h가 있고 이 스텝 간의 함수 값의 차이를 비교해 본다면
f(x+h) - f(x)

00:53:29.798 --> 00:53:34.895
그리고 그 스텝사이즈를 0으로 만들면 (h-&gt;0)
그것이 바로 어떤 점에서의 이 함수의 경사가 됩니다.

00:53:34.895 --> 00:53:38.333
그리고 이 수식은 다변수함수(multi-variable functions)
에서로 확장시킬 수 있습니다.

00:53:38.333 --> 00:53:42.612
실제로  x는 스칼라(값이 하나) 가 아니라 벡터 입니다.

00:53:42.612 --> 00:53:51.941
x가 벡터이기 때문에 위의 개념을 다변수로 확장시켜야 합니다.

00:53:51.941 --> 00:54:01.168
다변수인 상황에서의 미분으로 일반화시켜보면 gradient이고
gradient는 벡터 x의 각 요소를 편도함수들의 집합입니다.

00:54:01.168 --> 00:54:04.409
gradient의 모양은 x와 같습니다.
(입력이 3개면 gradient도 3개)

00:54:04.409 --> 00:54:12.391
그리고 gradient 의 각 요소가 알려주는 것은 바로
"우리가 그쪽으로 갈때 함수 f의 경사가 어떤지" 라는 것입니다.

00:54:12.391 --> 00:54:21.036
gradient를 통해 그런 유용한 정보를 얻을 수 있는 것입니다.
gradient는 편도함수들의 벡터입니다.

00:54:21.036 --> 00:54:25.657
gradient의 방향은 함수에서 "가장 많이 올라가는 방향" 이 됩니다.

00:54:25.657 --> 00:54:31.612
반대로 생각해보면, gradient의 반대 반향이라면
"가장 많이 내려갈 수 있는 방향" 이 되는 것입니다.

00:54:31.612 --> 00:54:37.418
그렇다면, 여러분이 만약에 특정 방향에서 얼마나 가파른지
알고싶으면 어떻게 해야 할까요?

00:54:37.418 --> 00:54:42.693
이는 그 방향의 유닛벡터와 gradient벡터를 내적할 것과 같습니다.

00:54:42.693 --> 00:54:50.198
gradient는 매우 중요합니다. 왜냐하면 gradient가 함수의 어떤
점에서의 선형 1차근사 함수를 알려주기 때문입니다.

00:54:50.198 --> 00:54:53.661
그래서 실제로 많은 딥러닝 알고리즘들이
gradient를 계산하고

00:54:53.661 --> 00:54:58.123
그 gradient를 여러분들이 파라미터 벡터를
반복적으로 업데이트할 때 사용하는 것입니다.

00:54:59.204 --> 00:55:04.812
컴퓨터로 이 gradient를 써먹을 수 있는 가장 단순한 방법 중 하나는

00:55:04.812 --> 00:55:06.955
유한 차분법(finite difference methods)를
이용하는 것입니다.

00:55:06.955 --> 00:55:09.488
다시 gradient의 극한 식으로 돌아가 봅시다.

00:55:09.488 --> 00:55:14.012
자 여기 왼쪽은 보면 파라미터 벡터 W가 있습니다.

00:55:14.012 --> 00:55:17.432
이 W를 사용하면 1.25정도의 Loss를 가지는군요

00:55:17.432 --> 00:55:23.922
우리가 할 일은 gradient "dW" 를 구하는 것입니다.
W와 모양은 같습니다.

00:55:23.922 --> 00:55:31.734
그리고 gradient의 각 요소가 말해주는 것은 우리가 그쪽 방향으로
아주 쬐끔 이동했을 때 Loss가 어떻게 변하는지 입니다.

00:55:31.734 --> 00:55:35.741
이걸 간단하게 유한 차분법으로 계산해 봅시다.

00:55:35.741 --> 00:55:41.902
일단 W가 있고, 지금 할 일은 W의 첫번째 요소(0.34) 에
아주 작은 값 h를 더해 보는 것입니다.

00:55:41.902 --> 00:55:45.842
그리고 loss를 다시 계산해 봅니다.

00:55:45.842 --> 00:55:53.792
여기에서 알 수 있는 것은, 우리가 첫 번째 요소를 조금 움직이면
Loss가 1.2534에서 1.25322로 감소한다는 것입니다.

00:55:55.945 --> 00:56:04.378
이제 극한 식을 이용해서 FDM으로 근사시킨
gradient를 구합니다.

00:56:04.378 --> 00:56:07.795
두 번째 요소에서도 이를 반복할 수 있겠습니다.

00:56:07.795 --> 00:56:13.728
이제 다시 첫 번째 요소의 값은 원래대로 돌려놓고
두 번째 요소를 아주 조금 증가시킵니다.

00:56:13.728 --> 00:56:21.165
그리고 다시 Loss를 계산하고 FDM을 이용해서
두 번째 요소 gradient의 근사치를 계산해 볼 수 있습니다.

00:56:21.165 --> 00:56:25.135
이런 세번째에도 하고 계속 반복합니다.

00:56:25.135 --> 00:56:29.150
이건 실제로는 정말 끔질한 방법입니다.
시간이 엄청 오래걸리거든요

00:56:29.150 --> 00:56:35.920
이 함수 f가 CNN같이 엄청 큰 함수였다면.
엄청 오래 걸렸을 것입니다.

00:56:35.920 --> 00:56:40.693
그리고 파라미터 W가 여기서는 10개뿐이 없지만

00:56:40.693 --> 00:56:46.446
엄청 크고 깊은 신경망이라면
파라미터가 수천 수억개 일 수도 있습니다.

00:56:46.446 --> 00:56:50.381
따라서 실제로는 이런식으로 gradient를 계산하지 않습니다.

00:56:50.381 --> 00:56:56.908
왜냐면 gradient 하나를 구하려고 수천개의 함수값을
일일이 다 계산해야 하기 떄문입니다.

00:56:56.908 --> 00:56:58.075
이건 엄청 느리고 안좋습니다.

00:56:59.351 --> 00:57:05.315
아마도 여러분들이 살면서 한번쯤은 미적수업을
들은적이 있을 것입니다.

00:57:05.315 --> 00:57:11.206
여기 이 두분들 덕분에, 우리는 단지 손실함수를
적어놓기만 하고

00:57:11.206 --> 00:57:17.372
미분이라는 마법의 헤머를 두드리기만 하면
gradient가 계산되어 나옵니다.

00:57:17.372 --> 00:57:21.658
해적적으로 푸는 것이 수치적으로 푸는 것 보다 더 효율적입니다.

00:57:21.658 --> 00:57:27.350
일단 더 정확하기도 할 뿐더러, 식 하나로 계산할 수 있기
때문에 계산 도 훨씬 더 빠릅니다.

00:57:28.945 --> 00:57:33.513
다시  W 그림으로 돌아가 봅시다.

00:57:33.513 --> 00:57:36.848
W 의 모든 원소를 순회하는 것이 아니라

00:57:36.848 --> 00:57:40.653
gradient를 나타내는 식이 뭔지만 먼저 찾아내고

00:57:40.653 --> 00:57:47.337
그걸 수식으로 내타내서 한번에 gradient dW를
계산해 버리는 것입니다.

00:57:47.337 --> 00:57:50.875
실제로 이 방법이 훨씬 더 좋습니다.

00:57:50.875 --> 00:57:56.738
요약하자면, 앞서 말한 수치적인 gradient는
간단하고 그럴듯 하긴 하지만

00:57:56.738 --> 00:57:58.745
실제로는 사용하지 않는다는 것입니다.

00:57:58.745 --> 00:58:05.301
실제 gradient 계산을 구현할때는 분석적인 방법을 이용합니다.

00:58:05.301 --> 00:58:10.610
하지만 흥미로운 점은 이런 수치적 gradient도
디버깅 툴로는 유용할 수 있다는 것입니다.

00:58:12.572 --> 00:58:17.770
우리가 Loss의 gradient를 계산하는 코드를 짜고 있다고 해봅시다.

00:58:17.770 --> 00:58:19.562
그것을 어떻게 디버깅하시겠습니까?

00:58:19.562 --> 00:58:25.684
여러분이 작성한 미분 코드가 잘 작동하는지를 어떻게
확인하실 것입니까?

00:58:25.684 --> 00:58:31.159
그런 상황에 흔히들 쓰는 방법은 바로 이
수치적 gradient를 사용하는 것입니다.

00:58:31.159 --> 00:58:35.141
유닛 테스트의 일종으로 여러분들의 코드를 확인할 수 있습니다.

00:58:35.141 --> 00:58:41.435
하지만 수치적인 방법은 엄청 느리고 부정확 하므로
이를 디버깅에 이용하고자 한다면

00:58:41.435 --> 00:58:46.755
파라미터의 스케일을 줄이는 편이 좋습니다.
그래야  디버깅이 오래 걸리지 않을 것입니다.

00:58:46.755 --> 00:58:51.721
여러분만의 gradient 계산 코드를 짤때 쓸만한
유용한 디버깅 전략 하나는 소개시켜 드렸습니다.

00:58:51.721 --> 00:58:58.610
실제로도 정말 많이 사용하고,
여러분들도 과제에서 사용하게 될 것입니다.

00:58:58.610 --> 00:59:01.834
일단 우리가 gradient를 계산하는 방법을 알고 나면

00:59:01.834 --> 00:59:13.152
이 세 줄짜리 간단한 알고리즘은 엄청 크고 복잡하고 싶은 신경망
알고리즘을 어떻게 학습시킬지에 대한 핵심 아이디어를 담 고 있습니다.

00:59:13.152 --> 00:59:19.544
Gradient  Descent에서는 우선 W를 임의의 값으로 초기화합니다.

00:59:19.544 --> 00:59:27.547
그리고 Loss와 gradient를 계산한 뒤에
가중치를 gradient의 반대 방향으로 업데이트합니다.

00:59:27.547 --> 00:59:34.047
gradient가 함수에서 증가하는 방향이기 때문에
-gradient를 해야 내려가는 방향이 되는 것입니다.

00:59:34.047 --> 00:59:40.774
그러니 -gradient 방향으로 아주 조금씩 이동할 것이고
이걸 영원히 반복하다 보면 결국에는 수렴할 것입니다.

00:59:40.774 --> 00:59:43.255
그렇게 되면 엄청 행복하겠지요...

00:59:43.255 --> 00:59:50.842
하지만 스텝 사이즈는 하이퍼 파라미터 입니다. 스텝 사이즈는
그 -gradient 방향으로 얼마나 나아가야 하는지를 알려줍니다.

00:59:50.842 --> 01:00:00.033
스텝사이즈는 Learning rate라고도 하며, 실제 학습을 할때 여러분이
정해줘 야 하는 가장 중요한 하이퍼파라미터 중 하나입니다.

01:00:00.033 --> 01:00:07.502
저의 경우에는 트레이닝을 시작할때 Leraning Rate는 제가 가장
먼저 체크하는 하이퍼파라미터입니다.

01:00:07.502 --> 01:00:12.434
모델 사이즈라던지 Regularization 의 강도라던지 하는 것들은
우선 나중으로 미뤄두고

01:00:12.434 --> 01:00:19.361
Learning rate를 올바르게 정해주는 것을 가장 먼저 합니다.

01:00:19.361 --> 01:00:25.212
여기 그림을 보면 2차원 공간의 아주 간단한 예시가 있습니다.

01:00:25.212 --> 01:00:30.051
여기 그릇처럼 보이는 것이 손실합수 입니다.

01:00:30.051 --> 01:00:36.598
가운데 빨간 부분이 낮은 Loss인 것이고

01:00:36.598 --> 01:00:41.187
테두리의 파란영역과 초록 영역은 Loss가 더 높은 곳입니다.
피해가야 겠죠

01:00:41.187 --> 01:00:44.750
자 이제 임의의 점에 W를 설정해 두겠습니다.

01:00:44.750 --> 01:00:51.387
이제 우리는 -gradient를 계산할 것이고 이를 통해
우리는 결국 가장 낮은 지점에 도달할 것입니다.

01:00:51.387 --> 01:00:56.407
그리고 이걸 계속 반복하게 되면 아마도 결국은
정확한 최저점에 도달하게 될 것입니다.

01:00:56.407 --> 01:01:04.358
실제로 한번 봅시다.

01:01:04.358 --> 01:01:15.266
우선 임의의 점에서 시작해서 매번 조금씩 계속 이동하는 것입니다.

01:01:15.266 --> 01:01:20.626
그리고 파라미터가 최저점으로 휘어져 들어가는 것을 볼 수 있습니다.

01:01:20.626 --> 01:01:24.241
우리가 낮은 loss를 원했기 때문에 이것은 정확히
우리가 바라던 것입니다.

01:01:24.241 --> 01:01:33.998
하지만 지금까지 본 예제는 아주 단순한 방법입니다.
매 스텝마다 -gradient의 방향으로만 이동한 뿐이죠

01:01:33.998 --> 01:01:40.885
하지만 다음 몇 강의동안 여러분은 더 쩌는 스텝을 볼 수 있을 것입니다.
Update Rule 이라고도 하는 방법이죠

01:01:40.885 --> 01:01:46.037
여러 스텝을 한번에 고려하는 더 쩌는 방법들이 존재합니다.

01:01:46.037 --> 01:01:54.610
기본적인 Gradient descent보다 실제 학습시에 더 좋은
성능을 보이는 것들입니다.

01:01:54.610 --> 01:02:01.054
맛보기로, 같은 문제를 푸는 다른
개쩌는 방법들을 몇가지 보여드리겠습니다.

01:02:01.054 --> 01:02:07.530
검정색은 이전에 본 것과 같은 스텝인 것이고
나머지 둘중 뭐가 뭔지 기억이 잘 안나지만

01:02:07.530 --> 01:02:11.580
어쨋든 나머지 두개는 좀 더 쩌는 Update rules입니다.

01:02:11.580 --> 01:02:15.929
이 방법들은 다음 스텝에 현재의 gradient 정보를 이용합니다.

01:02:15.929 --> 01:02:22.835
하나는 momentum을 이용한 것이고 다른 하나는
Adam optimizer를 이용한 방법입니다.

01:02:22.835 --> 01:02:25.389
저 자세한 사항은 다음 수업에서 다루도록 하겠습니다.

01:02:25.389 --> 01:02:29.795
그 방법들의 핵심은, Gradient Descent라는
기본적인 알고리즘을 사용하고 있고

01:02:29.795 --> 01:02:33.424
다음 스텝을 결정하기 위해서 이전의 모든 스텝의
gradient정보를 이용하는 것입니다.

01:02:33.424 --> 01:02:38.559
그래서 gradient 정보를 정확히 어떻게 이용할 것이냐
에 따라서 여러 Update rule이 존재하긴 하지만

01:02:38.559 --> 01:02:44.058
결국 기본적인 알고리즘은 바로 매 스텝 아래로 내려가는 것입니다.

01:02:50.022 --> 01:02:53.212
우리가 배워야 할 또 한가지가 있습니다.

01:02:53.212 --> 01:03:02.237
손실 함수를 정의했던 것을 생각해보면, Loss는 각 트레이닝
샘플을 분류기가 얼마나 "구리게" 분류하는지를 계산하는 것이였고

01:03:02.237 --> 01:03:08.314
그리고 전체 Loss는 전체 트레이닝 셋 Loss의 평균으로 사용했습니다.

01:03:08.314 --> 01:03:12.572
하지만 실제로는 N이 엄청 커 질수도 있습니다.

01:03:12.572 --> 01:03:19.199
첫 강의에서 말했던 ImageNet 데이터셋을 생각해보면
N은 130만개 입니다.

01:03:19.199 --> 01:03:23.208
따라서 Loss를 계산하는건 정말 오래 걸리는 작업이 됩니다.

01:03:23.208 --> 01:03:29.821
아마 수백만번의 계산이 필요한 것입니다.
그래서 그것은 정말로 느릴 수 있습니다.

01:03:29.821 --> 01:03:32.094
사실 gradient 는 선형 연산자 이기 때문에

01:03:32.094 --> 01:03:41.461
실제 gradient를 계산하는 과정을 살펴보면, Loss는 그저
각 데이터 Loss의 Gradient의 합이라는 것을 알 수 있습니다.

01:03:41.461 --> 01:03:48.469
그러니 gradient를 한번 더 계산하려면 , N개의 전체 트레이닝 셋
을 한번 더 돌면서 계산해야 하는 것입니다.

01:03:48.469 --> 01:03:56.978
N이 100만 이라면 엄청 느리게 되겠죠. W가 일일이 업데이트
되려면 엄청나게 많은 시간을 기다려야 할 것입니다.

01:03:56.978 --> 01:04:00.728
그래서 실제로는 stochastic gradient descent
라는 방법을 씁니다.

01:04:00.728 --> 01:04:05.697
전체 데이터 셋의 gradient과 loss를 계산하기 보다는

01:04:05.697 --> 01:04:12.540
Minibatch라는 작은 트레이닝 샘플 집합으로 나눠서
학습하는 것입니다.

01:04:12.540 --> 01:04:17.705
Minibatch는 보통 2의 승수로 정하며
32, 64, 128 을 보통 씁니다.

01:04:17.705 --> 01:04:25.047
따라서 이 작은 minibatch를 이용해서 Loss의 전체 합의 "추정치"와
실제 gradient의 "추정치"를 계산하는 것입니다.

01:04:25.047 --> 01:04:33.345
그래서 stochastic 하다는 것은 Monte Carlo Method의
실제 값 추정 방법과 유사하다고 볼 수 있습니다.

01:04:34.716 --> 01:04:38.945
알고리즘이 더 쩔어 졌지만
코드는 여전히 4줄이면 충분합니다.

01:04:38.945 --> 01:04:48.690
이제는 임의의 minibatch를 만들어내고, minibatch에서
Loss와 Gradient를 계산합니다. 그리고  W를 업데이트합니다.

01:04:48.690 --> 01:04:53.661
Loss의 "추정치" 와 Gradient의 "추정치" 를 사용하는 것입니다.

01:04:53.661 --> 01:04:59.811
그리고 앞으로, 이 좀 더 간지나는 Update Rules이
정확히 어떻게 여러 gradients들을 통합시키는지 알아 볼 것입니다.

01:04:59.811 --> 01:05:05.948
그리고 SGD는 거의 모든 DNN알고리즘에
사용되는 기본적인 학습 알고리즘입니다.

01:05:06.875 --> 01:05:14.970
Linear classifier를 이용해서 SGD로 어떻게 이것을 학습
시키는 지에 대한 웹 데모를 준비했습니다만

01:05:14.970 --> 01:05:23.269
지난 시간에 웹데모를 실패했기 때문에 실제 링크를 열지 않고
비디오로 보여드리겠습니다.

01:05:23.269 --> 01:05:25.339
[웃음]

01:05:25.339 --> 01:05:27.749
온라인에서 한번 접속해 보세요

01:05:27.749 --> 01:05:32.735
Linear classifier와 이를 Gradient descent로 학습
시키는 것에 대한 직관을 얻을 수 있습니다.

01:05:32.735 --> 01:05:40.146
여기 왼쪽에는 세개의 카테고리 클래스를 볼 수 있습니다.

01:05:40.146 --> 01:05:45.753
여기 초록, 파랑, 빨간 점들이 있고 이 점들이 트레이닝 샘플입니다.

01:05:45.753 --> 01:05:52.068
그리고 각 클래스에 해당하는 결정 경계를 그려 놨습니다.
배경 색은 해당하는 지역입니다.

01:05:52.068 --> 01:05:59.007
뿐만 아니라 방향도 있는데, 이 방향은
갹 세개의 클래스 스코어가 증가하는 방향입니다.

01:05:59.007 --> 01:06:12.176
그리고 접속해서 실제로 해보면 실제 W를 조정할 수가 있습니다.
W를 조절하면 결정 경계가 회전하는 것을 볼 수 있습니다.

01:06:12.176 --> 01:06:18.662
Bias를 조정하면 결정경계가 회전하지 않고
위아래로만 움직입니다.

01:06:18.662 --> 01:06:21.855
스텝도 만들어 놨습니다.
W를 업데이트도 할 수 있죠

01:06:21.855 --> 01:06:26.009
슬라이드바를 사용해서 스텝사이즈를 변경할 수 있습니다.

01:06:26.009 --> 01:06:32.874
스텝 사이즈를 크게 잡으니 , 지금 GD를 돌리고 있는데 결정
경계가 데이터에 핏하려고 날뛰고 있군요

01:06:34.553 --> 01:06:39.890
이제 날뛰지 않는군요. 그리고 손실 함수도
실시간으로 바뀔 수 있습니다.

01:06:39.890 --> 01:06:43.567
여러 SVM과 softmax 를 사용할 수 있습니다.

01:06:43.567 --> 01:06:50.219
그리고 여러분이 다양한 손실 함수를 적용해 보게 되면
손실 함수들이 일반적으로 같은 일을 하고 있다는 것을 알 수 있습니다.

01:06:50.219 --> 01:06:52.340
나눠진 지역들이 알고리즘 마다 비슷하긴 하지만

01:06:52.340 --> 01:06:54.945
결국 각각이 어떻게 학습이 종료되는지를 확인해보고

01:06:54.945 --> 01:07:00.743
여러 요소들의 trade-off를 따져보게 되면
조금씩 다르다는 것을 알 수 있습니다.

01:07:00.743 --> 01:07:09.178
그러니 GD를 통해  Linear classifier를 학습시키는게 실제로
어떻게 생겼는지를 보면서 직관을 얻으셨으면 좋겠습니다.

01:07:12.343 --> 01:07:16.245
이제 좀 다른 얘기를 해볼까 합니다.

01:07:16.245 --> 01:07:18.102
이미지의 특징에 관한 것입니다.

01:07:18.102 --> 01:07:27.434
지금까지 Linear classifier에 대해 이야기해 보았습니다.
실제 Raw 이미지 픽셀을 입력으로 받는 방식이었죠

01:07:28.464 --> 01:07:33.343
지난 강의에서 말씀 드렸듯이
이런 방법은 좋은 방법은 아닙니다.

01:07:33.343 --> 01:07:36.233
Multi-Modality 와 같은 것들 때문이죠
(말 머리 두개)

01:07:36.233 --> 01:07:42.789
실제로는 영상 자체를 입력으로 사용하는 것은
성능이 좋지 않습니다.

01:07:42.789 --> 01:07:49.592
그래서 DNN이 유행하기 전에 주로 쓰는 방법은
두가지 스테이지를 거치는 방법이었습니다.

01:07:49.592 --> 01:07:53.916
첫번 째는, 이미지가 있으면 여러가지 특징 표현을 계산하는 것입니다.

01:07:53.916 --> 01:08:00.179
이런 특징 표현은 이미지의 모양새와 관련된 것일 수 있습니다.

01:08:00.179 --> 01:08:05.137
그리고 여러 특징 표현들은 한데 연결시켜(Concat)
하나의 특징 벡터로 만듭니다.

01:08:05.137 --> 01:08:12.902
그러면 이 특징 벡터가 Linear classifier의 입력으로 들어가는
것입니다.

01:08:12.902 --> 01:08:17.700
여기에서의 모티브는 , 여기 그림과 같은
트레이닝 셋이 있다고 해 보면

01:08:17.701 --> 01:08:22.244
빨간 점들이 가운데 있고 그 주변에 파란 점들이 있죠

01:08:22.244 --> 01:08:29.157
이런 데이터 셋의 경우에는 Linear한 결정 경제를 그릴
방법이 없는 것입니다.

01:08:29.157 --> 01:08:32.155
이런 예시를 지난 강의에서 더 살펴 봤었습니다.

01:08:32.156 --> 01:08:36.660
만약 우리가 적절하게 특징 변환을 해본다면,
이경우에는 극좌표계로 바꾼 것입니다.

01:08:36.660 --> 01:08:43.677
그 복잡하던 데이터가, 변환 후에
선형으로 분리가 가능하게 바뀌었습니다.

01:08:43.677 --> 01:08:46.858
실제로도 Linear classifier로 완벽하게
분리할 수 있습니다.

01:08:46.858 --> 01:08:55.129
이런 기법들은 여러분의 문제를 풀 수 있도록 하려면 어떤 특징
변환이 필요한가 를 알아내는 것들입니다.

01:08:55.129 --> 01:08:59.751
이미지의 경우 픽셀들을 극좌표계로 바꾸는 것은
전혀 말이 안되는 일이지만

01:08:59.751 --> 01:09:04.749
극좌표계로 변환하는 것을 일종의 특징 변환이라 생각한다면
말이 되는 것입니다.

01:09:04.749 --> 01:09:10.391
그리고 이것은 실제로 분류기에 Raw 이미지를 넣는것 보다
성능이 더 좋을지도 모릅니다.

01:09:10.392 --> 01:09:16.343
특징 변환의 한 예를 들어보자면 컬러 히스토그램이 있습니다.

01:09:16.343 --> 01:09:23.985
이미지에서 Hue 값만 뽑아서
모든 픽셀을 각 양동이에 넣는 것입니다.

01:09:23.986 --> 01:09:31.162
한 필셀은 해당하는 색의 양동이에 넣고
각 양동이에 들어있는 픽셀의 개수를 세는 것입니다.

01:09:31.162 --> 01:09:34.638
이는 이미지가 적체적으로 어떤 색인지를 알려줍니다.

01:09:34.639 --> 01:09:40.938
이 개구리의 예를 보면 초록색이 많은걸 알 수 있습니다.
자주색이나 붉은색은 별로 없습니다.

01:09:40.938 --> 01:09:44.043
실제로 사용하는 간단한 특징 벡터라고 볼 수 있습니다.

01:09:45.108 --> 01:09:53.219
NN이 뜨기 전에 인기있었던 또 다른 특징 벡터중 하나는 바로
Histogram of oriented gradients(HOG) 입니다.

01:09:53.220 --> 01:10:00.046
첫 강의를 생각해보면 Hubel 과 Wiesel이 이런 Oriented
edges가 인간의 시각시스템에서 정말 중요하다고 했습니다.

01:10:00.046 --> 01:10:09.974
HOG도 그와 같은 직관을 가지고 있으며
Local orientation edges를 측정합니다.

01:10:09.974 --> 01:10:16.354
실제로 하는 일을 보면 이미지가 있으면
8x8로 픽셀을 나눕니다.

01:10:16.354 --> 01:10:22.268
그리고 이 8x8 픽셀 지역 내에서, 가장 지배적인
edge의 방향을 계산하고

01:10:22.268 --> 01:10:27.776
그리고 edge directions을 양자화해서 양동이에 넣는 것입니다.

01:10:27.776 --> 01:10:31.857
그리고 다양한 edge oreirentations에 대한 히스토그램을
계산하는 것입니다.

01:10:31.857 --> 01:10:40.204
그러면 전체 특징 벡터는, 각각의 모든 8x8 지역들이 가진 "edge
orientation에 대한 히스토그램" 이 되는 것입니다.

01:10:41.660 --> 01:10:47.029
이전에 봤던 컬러 히스토그램이랑은 좀 다르죠

01:10:47.029 --> 01:10:51.082
컬러 히스토그램은 이미지 전체적으로 어떤 색이 있는지를
나타냈습니다.

01:10:51.082 --> 01:10:55.305
반면 HOG는 이미지 내에 전반적으로 어떤 종류의
edge정보가 있는지를 나타냅니다.

01:10:55.305 --> 01:11:01.191
이미지를 여러 부분으로 지역화해서,
지역적으로 어떤 edge가 존재하는지도 알 수 있습니다.

01:11:01.191 --> 01:11:04.938
그래서 이 개구리의 경우를 보면
이파리 위에 앉아있는 것을 볼 수 있습니다.

01:11:04.938 --> 01:11:07.561
그리고 이파리들은
주로 대각선 edge를 가지고 있습니다.

01:11:07.561 --> 01:11:14.667
그리고 실제 HOG를 시각화해 보면
이파리 부분에 많은 대각 edge가 있다는 것을 알 수 있습니다.

01:11:14.667 --> 01:11:19.340
이것이 바로 HOG의 특징표현이 가지고 있는 것입니다.

01:11:19.340 --> 01:11:25.702
HOG는 영상 인식에서 정말 많이 활용한 특징벡터입니다.
엄청 오래전에 사용했던 것이 아닙니다.

01:11:26.573 --> 01:11:32.810
또 하나의 특징 표현이 있는데 바로 bag of words입니다.

01:11:32.810 --> 01:11:36.355
이 아이디어는 자연어처리(NLP)에서 영감을 받은 것인데요

01:11:36.355 --> 01:11:40.799
어떤 문장이 있고, BOW에서 이 문장을 표현하는 방법은

01:11:40.799 --> 01:11:45.732
바로 문장의 여러 단어의 발생 빈도를 세서 특징 벡터로
사용하는 것입니다.

01:11:45.732 --> 01:11:49.664
이 직관을 그대로 이미지에 적용한 것입니다.

01:11:49.664 --> 01:11:54.288
하지만 BOW를 적용하려고 하는데 이미지에 적용하려니
쉬운 문제가 아니였습니다.

01:11:54.288 --> 01:11:57.965
그래서 "시각 단어(visual words)"라고 하는
우리만의 용어를 정의해야 했습니다.

01:11:58.880 --> 01:12:01.106
여기에서는 2단계의 과정이 있습니다.

01:12:01.106 --> 01:12:09.723
엄청 많은 이미지를 가지고, 그 이미지들은 임의대로 조각냅니다.
그리고 그 조각들을 K-means와 같은 알고리즘으로 군집화합니다.

01:12:09.723 --> 01:12:17.139
이미지내의 다양한 것들을 표현할 수 있는
다양한 군집들을 만들어 내는 것입니다.

01:12:17.139 --> 01:12:23.335
오른쪽 예를 보면, 이것은 이미지들에서 다양한 이미지 패치를
뽑아내서 군집화 시켜 놓은 실제 예시입니다.

01:12:23.335 --> 01:12:30.552
군집화 단계를 거치고나면, 시각 단어(visual words)는
빨간색, 파랑색, 노랑색과 같은 다양한 색을 포착해냅니다.

01:12:30.552 --> 01:12:34.556
분만 아니라 다양한 종류의
다양한 방향의  oriented edges또한 포착할 수 있습니다.

01:12:34.556 --> 01:12:40.480
그리고 이건은 매우 흥미롭습니다. 왜냐하면 이런 edges들을
데이터 중심적인 방법을 통해 얻어낸 것이기 때문입니다.

01:12:40.480 --> 01:12:44.291
이런 시각 단어(visual words) 집합인 Codebook을 만들고 나면

01:12:44.291 --> 01:12:52.468
그러면 어떤 이미지가 있으면, 이 이미지에서의 시각 단어들의
발생 빈도를 통해서 이미지를 인코딩 할 수 있는 것입니다.

01:12:52.468 --> 01:12:59.427
그리고 이는 이 이미지가 어떻게 생겼는지에 대한
다양한 정보를 제공하는 것입니다.

01:12:59.427 --> 01:13:04.638
그리고 BOW는 Fei-Fei 교수님께서 대학원시절에 만든 것입니다.

01:13:04.638 --> 01:13:08.972
여러분이 지금까지 봤던 것들이 실제로 엄청 오래전에
쓰인 것이 아닙니다.

01:13:10.783 --> 01:13:20.886
나중에 설명한 내용이긴 하지만
Image classification의 pipleline은 이렇게 생겼습니다.

01:13:20.886 --> 01:13:31.173
5~10년 전까지만 해도 이미지를 입력받으면 BOW나 HOG와 같은
다양한 특징 표현을 계산하고,

01:13:31.173 --> 01:13:38.590
계산한 특징들을 한데 모아 연결해서, 추출된 그 특징들을
Linear classifier의 입력으로 사용했습니다.

01:13:38.590 --> 01:13:44.576
제가 어느정도 단순화시키긴 했지만, 대부분은 일반적으로
이런 직관이라고 보시면 되겠습니다.

01:13:44.576 --> 01:13:53.563
특징이 한번 추출되면 feature extractor는 classier를
트레이닝하는 동안 변하지 않습니다.

01:13:53.563 --> 01:13:57.907
트레이닝 중에는 오직 Linear classifier만 훈련이 됩니다.

01:13:57.907 --> 01:14:06.486
그리고 CNN이나 DNN으로 넘어가 보자면
실제로 크게 다르지 않습니다.

01:14:06.486 --> 01:14:12.687
유일하게 다른점이 있다면 이미 만들어 놓은 특징들을 쓰기 보다는
데이터로부터 특징들을 직접 학습하려 한다는 것입니다.

01:14:12.687 --> 01:14:21.488
터그렇기 때문에 raw 픽셀이 CNN에 그대로 들어가고
여러 레이어를 거쳐서 데이터를 통한 특징 표현을 직접 만들어냅니다.

01:14:21.488 --> 01:14:28.787
따라서 Linear classifier만 훈련하는게 아니라 가중치 전체를
한꺼번에 학습하는 것입니다.

01:14:30.329 --> 01:14:39.329
그럼 다음시간에는 CNN에 대해 더 심도깊에 살펴볼 것이고
역전파(backpropagarion) 또한 알아볼 것입니다.